diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-03-29 00:47:55 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-03-29 00:55:14 +0900 |
| commit | d30dfc89bf1b673b2fdc0638766b930adaec228c (patch) | |
| tree | 739d8826451947adfeb526ef1adeb1db397a9af4 /vhosts/blog/public/posts | |
| parent | f65ec15aaf8fc46685c39d721cab82f64baead8c (diff) | |
| download | nsfisis.dev-d30dfc89bf1b673b2fdc0638766b930adaec228c.tar.gz nsfisis.dev-d30dfc89bf1b673b2fdc0638766b930adaec228c.tar.zst nsfisis.dev-d30dfc89bf1b673b2fdc0638766b930adaec228c.zip | |
feat(blog/nuldoc): migrate syntax highlighter from highlight.js to shiki.js
Diffstat (limited to 'vhosts/blog/public/posts')
49 files changed, 2631 insertions, 2317 deletions
diff --git a/vhosts/blog/public/posts/2021-03-05/my-first-post/index.html b/vhosts/blog/public/posts/2021-03-05/my-first-post/index.html index 4e00a39d..9170e5f2 100644 --- a/vhosts/blog/public/posts/2021-03-05/my-first-post/index.html +++ b/vhosts/blog/public/posts/2021-03-05/my-first-post/index.html @@ -13,8 +13,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>My First Post|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> diff --git a/vhosts/blog/public/posts/2021-03-30/phperkaigi-2021/index.html b/vhosts/blog/public/posts/2021-03-30/phperkaigi-2021/index.html index 4dfee57e..e70cf152 100644 --- a/vhosts/blog/public/posts/2021-03-30/phperkaigi-2021/index.html +++ b/vhosts/blog/public/posts/2021-03-30/phperkaigi-2021/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>PHPerKaigi 2021|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> diff --git a/vhosts/blog/public/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html b/vhosts/blog/public/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html index b6baad39..d99fc02c 100644 --- a/vhosts/blog/public/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html +++ b/vhosts/blog/public/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>【C++】 属性構文の属性名にはキーワードが使える|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -74,25 +73,27 @@ タイトル落ち。まずはこのコードを見て欲しい。 </p> - <pre class="highlight" language="cpp"><code class="highlight"><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><iostream></span></span> - -[[<span class="hljs-keyword">alignas</span>]] [[<span class="hljs-keyword">alignof</span>]] [[<span class="hljs-keyword">and</span>]] [[<span class="hljs-keyword">and_eq</span>]] [[<span class="hljs-keyword">asm</span>]] [[<span class="hljs-keyword">auto</span>]] [[<span class="hljs-keyword">bitand</span>]] -[[<span class="hljs-keyword">bitor</span>]] [[<span class="hljs-type">bool</span>]] [[<span class="hljs-keyword">break</span>]] [[<span class="hljs-keyword">case</span>]] [[<span class="hljs-keyword">catch</span>]] [[<span class="hljs-type">char</span>]] [[<span class="hljs-type">char16_t</span>]] -[[<span class="hljs-type">char32_t</span>]] [[<span class="hljs-keyword">class</span>]] [[<span class="hljs-keyword">compl</span>]] [[<span class="hljs-type">const</span>]] [[<span class="hljs-keyword">const_cast</span>]] [[<span class="hljs-keyword">constexpr</span>]] -[[<span class="hljs-keyword">continue</span>]] [[<span class="hljs-keyword">decltype</span>]] [[<span class="hljs-keyword">default</span>]] [[<span class="hljs-keyword">delete</span>]] [[<span class="hljs-keyword">do</span>]] [[<span class="hljs-type">double</span>]] -[[<span class="hljs-keyword">dynamic_cast</span>]] [[<span class="hljs-keyword">else</span>]] [[<span class="hljs-keyword">enum</span>]] [[<span class="hljs-keyword">explicit</span>]] [[<span class="hljs-keyword">export</span>]] [[<span class="hljs-keyword">extern</span>]] [[<span class="hljs-literal">false</span>]] -[[<span class="hljs-keyword">final</span>]] [[<span class="hljs-type">float</span>]] [[<span class="hljs-keyword">for</span>]] [[<span class="hljs-keyword">friend</span>]] [[<span class="hljs-keyword">goto</span>]] [[<span class="hljs-keyword">if</span>]] [[<span class="hljs-keyword">inline</span>]] [[<span class="hljs-type">int</span>]] -[[<span class="hljs-type">long</span>]] [[<span class="hljs-keyword">mutable</span>]] [[<span class="hljs-keyword">namespace</span>]] [[<span class="hljs-keyword">new</span>]] [[<span class="hljs-keyword">noexcept</span>]] [[<span class="hljs-keyword">not</span>]] [[<span class="hljs-keyword">not_eq</span>]] -[[<span class="hljs-literal">nullptr</span>]] [[<span class="hljs-keyword">operator</span>]] [[<span class="hljs-keyword">or</span>]] [[<span class="hljs-keyword">or_eq</span>]] [[<span class="hljs-keyword">override</span>]] [[<span class="hljs-keyword">private</span>]] -[[<span class="hljs-keyword">protected</span>]] [[<span class="hljs-keyword">public</span>]] [[<span class="hljs-keyword">register</span>]] [[<span class="hljs-keyword">reinterpret_cast</span>]] [[<span class="hljs-keyword">return</span>]] [[<span class="hljs-type">short</span>]] -[[<span class="hljs-type">signed</span>]] [[<span class="hljs-keyword">sizeof</span>]] [[<span class="hljs-type">static</span>]] [[<span class="hljs-keyword">static_assert</span>]] [[<span class="hljs-keyword">static_cast</span>]] [[<span class="hljs-keyword">struct</span>]] -[[<span class="hljs-keyword">switch</span>]] [[<span class="hljs-keyword">template</span>]] [[<span class="hljs-keyword">this</span>]] [[<span class="hljs-keyword">thread_local</span>]] [[<span class="hljs-keyword">throw</span>]] [[<span class="hljs-literal">true</span>]] [[<span class="hljs-keyword">try</span>]] -[[<span class="hljs-keyword">typedef</span>]] [[<span class="hljs-keyword">typeid</span>]] [[<span class="hljs-keyword">typename</span>]] [[<span class="hljs-keyword">union</span>]] [[<span class="hljs-type">unsigned</span>]] -[[<span class="hljs-keyword">virtual</span>]] [[<span class="hljs-type">void</span>]] [[<span class="hljs-keyword">volatile</span>]] [[<span class="hljs-type">wchar_t</span>]] [[<span class="hljs-keyword">while</span>]] [[<span class="hljs-keyword">xor</span>]] [[<span class="hljs-keyword">xor_eq</span>]] -<span class="hljs-comment">// [[using]]</span> -<span class="hljs-type">int</span> <span class="hljs-built_in">main</span>() { - std::cout << <span class="hljs-string">"Hello, World!"</span> << std::endl; -}</code></pre> + <div class="codeblock" language="cpp"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">#include</span><span style="color:#032F62"> <iostream></span></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">alignas</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">alignof</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">and</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">and_eq</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">asm</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">auto</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">bitand</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">bitor</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">bool</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">break</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">case</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">catch</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">char</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">char16_t</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">char32_t</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">class</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">compl</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">const</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">const_cast</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">constexpr</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">continue</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">decltype</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">default</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">delete</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">do</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">double</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">dynamic_cast</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">else</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">enum</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">explicit</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">export</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">extern</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">false</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">final</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">float</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">for</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">friend</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">goto</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">if</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">inline</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">int</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">long</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">mutable</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">namespace</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">new</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">noexcept</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">not</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">not_eq</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">nullptr</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">operator</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">or</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">or_eq</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">override</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">private</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">protected</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">public</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">register</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">reinterpret_cast</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">return</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">short</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">signed</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">sizeof</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">static</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">static_assert</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">static_cast</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">struct</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">switch</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">template</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">this</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">thread_local</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">throw</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">true</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">try</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">typedef</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">typeid</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">typename</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">union</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">unsigned</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#6F42C1">virtual</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">void</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">volatile</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">wchar_t</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">while</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">xor</span><span style="color:#005CC5">]]</span><span style="color:#005CC5"> [[</span><span style="color:#6F42C1">xor_eq</span><span style="color:#005CC5">]]</span></span> +<span class="line"><span style="color:#6A737D">// [[using]]</span></span> +<span class="line"><span style="color:#D73A49">int</span><span style="color:#6F42C1"> main</span><span style="color:#24292E">() {</span></span> +<span class="line"><span style="color:#6F42C1"> std</span><span style="color:#24292E">::cout </span><span style="color:#D73A49"><<</span><span style="color:#032F62"> "Hello, World!"</span><span style="color:#D73A49"> <<</span><span style="color:#6F42C1"> std</span><span style="color:#24292E">::endl;</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <blockquote> <p> @@ -137,8 +138,10 @@ 上のコードでは <code>[[using]]</code> をコメントアウトしているが、これは <code>using</code> キーワードのみ属性構文の中で意味を持つからであり、このコメントアウトを外すとコンパイルに失敗する。 </p> - <pre class="highlight" language="cpp"><code class="highlight"><span class="hljs-comment">// using の例</span> -[[<span class="hljs-keyword">using</span> foo: attr1, attr2]] <span class="hljs-type">int</span> x; <span class="hljs-comment">// [[foo::attr1, foo::attr2]] の糖衣構文</span></code></pre> + <div class="codeblock" language="cpp"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D">// using の例</span></span> +<span class="line"><span style="color:#005CC5">[[</span><span style="color:#D73A49">using</span><span style="color:#6F42C1"> foo</span><span style="color:#005CC5">: </span><span style="color:#6F42C1">attr1</span><span style="color:#005CC5">, </span><span style="color:#6F42C1">attr2</span><span style="color:#005CC5">]]</span><span style="color:#D73A49"> int</span><span style="color:#24292E"> x;</span><span style="color:#6A737D"> // [[foo::attr1, foo::attr2]] の糖衣構文</span></span></code></pre> + </div> <p> C++17 の仕様も見てみる (正確には標準化前のドラフト)。 diff --git a/vhosts/blog/public/posts/2021-10-02/python-unbound-local-error/index.html b/vhosts/blog/public/posts/2021-10-02/python-unbound-local-error/index.html index 91ec5d0a..f3a11356 100644 --- a/vhosts/blog/public/posts/2021-10-02/python-unbound-local-error/index.html +++ b/vhosts/blog/public/posts/2021-10-02/python-unbound-local-error/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>【Python】 クロージャとUnboundLocalError: local variable 'x' referenced before assignment|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -78,13 +77,15 @@ Python でクロージャを作ろうと、次のようなコードを書いた。 </p> - <pre class="highlight" language="python"><code class="highlight"><span class="hljs-keyword">def</span> <span class="hljs-title function_">f</span>(): - x = <span class="hljs-number">0</span> - <span class="hljs-keyword">def</span> <span class="hljs-title function_">g</span>(): - x += <span class="hljs-number">1</span> - g() - -f()</code></pre> + <div class="codeblock" language="python"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">def</span><span style="color:#6F42C1"> f</span><span style="color:#24292E">():</span></span> +<span class="line"><span style="color:#24292E"> x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> 0</span></span> +<span class="line"><span style="color:#D73A49"> def</span><span style="color:#6F42C1"> g</span><span style="color:#24292E">():</span></span> +<span class="line"><span style="color:#24292E"> x </span><span style="color:#D73A49">+=</span><span style="color:#005CC5"> 1</span></span> +<span class="line"><span style="color:#24292E"> g()</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">f()</span></span></code></pre> + </div> <p> 関数 <code>g</code> から 関数 <code>f</code> のスコープ内で定義された変数 <code>x</code> を参照し、それに 1 を足そうとしている。 これを実行すると <code>x += 1</code> の箇所でエラーが発生する。 @@ -100,27 +101,31 @@ f()</code></pre> local変数 <code>x</code> が代入前に参照された、とある。これは、<code>f</code> の <code>x</code> を参照するのではなく、新しく別の変数を <code>g</code> 内に作ってしまっているため。前述のコードを宣言と代入を便宜上分けて書き直すと次のようになる。<code>var</code> を変数宣言のための構文として擬似的に利用している。 </p> - <pre class="highlight" language="python"><code class="highlight"><span class="hljs-comment"># 注: var は正しい Python の文法ではない。上記参照のこと</span> -<span class="hljs-keyword">def</span> <span class="hljs-title function_">f</span>(): - var x <span class="hljs-comment"># f の local変数 'x' を宣言</span> - x = <span class="hljs-number">0</span> <span class="hljs-comment"># x に 0 を代入</span> - <span class="hljs-keyword">def</span> <span class="hljs-title function_">g</span>(): <span class="hljs-comment"># f の内部関数 g を定義</span> - var x <span class="hljs-comment"># g の local変数 'x' を宣言</span> - <span class="hljs-comment"># たまたま f にも同じ名前の変数があるが、それとは別の変数</span> - x += <span class="hljs-number">1</span> <span class="hljs-comment"># x に 1 を加算 (x = x + 1 の糖衣構文)</span> - <span class="hljs-comment"># 加算する前の値を参照しようとするが、まだ代入されていないためエラー</span> - g()</code></pre> + <div class="codeblock" language="python"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D"># 注: var は正しい Python の文法ではない。上記参照のこと</span></span> +<span class="line"><span style="color:#D73A49">def</span><span style="color:#6F42C1"> f</span><span style="color:#24292E">():</span></span> +<span class="line"><span style="color:#24292E"> var x </span><span style="color:#6A737D"># f の local変数 'x' を宣言</span></span> +<span class="line"><span style="color:#24292E"> x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> 0</span><span style="color:#6A737D"> # x に 0 を代入</span></span> +<span class="line"><span style="color:#D73A49"> def</span><span style="color:#6F42C1"> g</span><span style="color:#24292E">(): </span><span style="color:#6A737D"># f の内部関数 g を定義</span></span> +<span class="line"><span style="color:#24292E"> var x </span><span style="color:#6A737D"># g の local変数 'x' を宣言</span></span> +<span class="line"><span style="color:#6A737D"> # たまたま f にも同じ名前の変数があるが、それとは別の変数</span></span> +<span class="line"><span style="color:#24292E"> x </span><span style="color:#D73A49">+=</span><span style="color:#005CC5"> 1</span><span style="color:#6A737D"> # x に 1 を加算 (x = x + 1 の糖衣構文)</span></span> +<span class="line"><span style="color:#6A737D"> # 加算する前の値を参照しようとするが、まだ代入されていないためエラー</span></span> +<span class="line"><span style="color:#24292E"> g()</span></span></code></pre> + </div> <p> 当初の意図を表現するには、次のように書けばよい。 </p> - <pre class="highlight" language="python"><code class="highlight"><span class="hljs-keyword">def</span> <span class="hljs-title function_">f</span>(): - x = <span class="hljs-number">0</span> - <span class="hljs-keyword">def</span> <span class="hljs-title function_">g</span>(): - <span class="hljs-keyword">nonlocal</span> x <span class="hljs-comment">## (*)</span> - x += <span class="hljs-number">1</span> - g()</code></pre> + <div class="codeblock" language="python"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">def</span><span style="color:#6F42C1"> f</span><span style="color:#24292E">():</span></span> +<span class="line"><span style="color:#24292E"> x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> 0</span></span> +<span class="line"><span style="color:#D73A49"> def</span><span style="color:#6F42C1"> g</span><span style="color:#24292E">():</span></span> +<span class="line"><span style="color:#D73A49"> nonlocal</span><span style="color:#24292E"> x </span><span style="color:#6A737D">## (*)</span></span> +<span class="line"><span style="color:#24292E"> x </span><span style="color:#D73A49">+=</span><span style="color:#005CC5"> 1</span></span> +<span class="line"><span style="color:#24292E"> g()</span></span></code></pre> + </div> <p> <code>(*)</code> のように、<code>nonlocal</code> を追加する。これにより一つ外側のスコープ (<code>g</code> の一つ外側 = <code>f</code>) で定義されている <code>x</code> を探しに行くようになる。 diff --git a/vhosts/blog/public/posts/2021-10-02/ruby-detect-running-implementation/index.html b/vhosts/blog/public/posts/2021-10-02/ruby-detect-running-implementation/index.html index 0e9ee932..cf2eb729 100644 --- a/vhosts/blog/public/posts/2021-10-02/ruby-detect-running-implementation/index.html +++ b/vhosts/blog/public/posts/2021-10-02/ruby-detect-running-implementation/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>【Ruby】 自身を実行している処理系の種類を判定する|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -83,12 +82,14 @@ 上記ページの例から引用する: </p> - <pre class="highlight" language="shell-session"><code>$ ruby-1.9.1 -ve 'p RUBY_ENGINE' -ruby 1.9.1p0 (2009-03-04 revision 22762) [x86_64-linux] -"ruby" -$ jruby -ve 'p RUBY_ENGINE' -jruby 1.2.0 (ruby 1.8.6 patchlevel 287) (2009-03-16 rev 9419) [i386-java] -"jruby"</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ ruby-1.9.1 -ve 'p RUBY_ENGINE'</span></span> +<span class="line"><span>ruby 1.9.1p0 (2009-03-04 revision 22762) [x86_64-linux]</span></span> +<span class="line"><span>"ruby"</span></span> +<span class="line"><span>$ jruby -ve 'p RUBY_ENGINE'</span></span> +<span class="line"><span>jruby 1.2.0 (ruby 1.8.6 patchlevel 287) (2009-03-16 rev 9419) [i386-java]</span></span> +<span class="line"><span>"jruby"</span></span></code></pre> + </div> <p> それぞれの処理系がどのような値を返すかだが、stack overflow に良い質問と回答があった。 @@ -208,10 +209,12 @@ jruby 1.2.0 (ruby 1.8.6 patchlevel 287) (2009-03-16 rev 9419) [i386-java] <a href="https://github.com/mruby/mruby/blob/ed29d74bfd95362eaeb946fcf7e865d80346b62b/include/mruby/version.h#L32-L35" rel="noreferrer" target="_blank">mruby 該当部分のソース</a> より引用: </p> - <pre class="highlight" language="c"><code class="highlight"><span class="hljs-comment">/* -* Ruby engine. -*/</span> -<span class="hljs-meta">#<span class="hljs-keyword">define</span> MRUBY_RUBY_ENGINE <span class="hljs-string">"mruby"</span></span></code></pre> + <div class="codeblock" language="c"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D">/*</span></span> +<span class="line"><span style="color:#6A737D">* Ruby engine.</span></span> +<span class="line"><span style="color:#6A737D">*/</span></span> +<span class="line"><span style="color:#D73A49">#define</span><span style="color:#6F42C1"> MRUBY_RUBY_ENGINE</span><span style="color:#032F62"> "mruby"</span></span></code></pre> + </div> </div> </article> </main> diff --git a/vhosts/blog/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html b/vhosts/blog/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html index a11a2f15..76f7058c 100644 --- a/vhosts/blog/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html +++ b/vhosts/blog/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>【Ruby】 then キーワードと case in|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -83,36 +82,40 @@ 使われることは稀だが、Ruby では <code>then</code> がキーワードになっている。次のように使う: </p> - <pre class="highlight" language="ruby"><code class="highlight"><span class="hljs-keyword">if</span> cond <span class="hljs-keyword">then</span> - puts <span class="hljs-string">"Y"</span> -<span class="hljs-keyword">else</span> - puts <span class="hljs-string">"N"</span> -<span class="hljs-keyword">end</span></code></pre> + <div class="codeblock" language="ruby"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">if</span><span style="color:#24292E"> cond </span><span style="color:#D73A49">then</span></span> +<span class="line"><span style="color:#005CC5"> puts</span><span style="color:#032F62"> "Y"</span></span> +<span class="line"><span style="color:#D73A49">else</span></span> +<span class="line"><span style="color:#005CC5"> puts</span><span style="color:#032F62"> "N"</span></span> +<span class="line"><span style="color:#D73A49">end</span></span></code></pre> + </div> <p> このキーワードが現れうる場所はいくつかあり、<code>if</code>、<code>unless</code>、<code>rescue</code>、<code>case</code> 構文がそれに当たる。 上記のように、何か条件を書いた後 <code>then</code> を置き、式がそこで終了していることを示すマーカーとして機能する。 </p> - <pre class="highlight" language="ruby"><code class="highlight"><span class="hljs-comment"># Example:</span> - -<span class="hljs-keyword">if</span> x <span class="hljs-keyword">then</span> - a -<span class="hljs-keyword">end</span> - -<span class="hljs-keyword">unless</span> x <span class="hljs-keyword">then</span> - a -<span class="hljs-keyword">end</span> - -<span class="hljs-keyword">begin</span> - a -<span class="hljs-keyword">rescue</span> <span class="hljs-keyword">then</span> - b -<span class="hljs-keyword">end</span> - -<span class="hljs-keyword">case</span> x -<span class="hljs-keyword">when</span> p <span class="hljs-keyword">then</span> - a -<span class="hljs-keyword">end</span></code></pre> + <div class="codeblock" language="ruby"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D"># Example:</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">if</span><span style="color:#24292E"> x </span><span style="color:#D73A49">then</span></span> +<span class="line"><span style="color:#24292E"> a</span></span> +<span class="line"><span style="color:#D73A49">end</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">unless</span><span style="color:#24292E"> x </span><span style="color:#D73A49">then</span></span> +<span class="line"><span style="color:#24292E"> a</span></span> +<span class="line"><span style="color:#D73A49">end</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">begin</span></span> +<span class="line"><span style="color:#24292E"> a</span></span> +<span class="line"><span style="color:#D73A49">rescue</span><span style="color:#D73A49"> then</span></span> +<span class="line"><span style="color:#24292E"> b</span></span> +<span class="line"><span style="color:#D73A49">end</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">case</span><span style="color:#24292E"> x</span></span> +<span class="line"><span style="color:#D73A49">when</span><span style="color:#005CC5"> p</span><span style="color:#D73A49"> then</span></span> +<span class="line"><span style="color:#24292E"> a</span></span> +<span class="line"><span style="color:#D73A49">end</span></span></code></pre> + </div> </section> <section id="section--why-then-is-usually-unnecessary"> @@ -121,17 +124,21 @@ 普通 Ruby のコードで <code>then</code> を書くことはない。なぜか。次のコードを実行してみるとわかる。 </p> - <pre class="highlight" language="ruby"><code class="highlight"><span class="hljs-keyword">if</span> <span class="hljs-literal">true</span> puts <span class="hljs-string">'Hello, World!'</span> <span class="hljs-keyword">end</span></code></pre> + <div class="codeblock" language="ruby"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">if</span><span style="color:#005CC5"> true</span><span style="color:#005CC5"> puts</span><span style="color:#032F62"> 'Hello, World!'</span><span style="color:#D73A49"> end</span></span></code></pre> + </div> <p> 次のような構文エラーが出力される。 </p> - <pre class="highlight"><code>20:1: syntax error, unexpected local variable or method, expecting `then' or ';' or '\n' -if true puts 'Hello, World!' end - ^~~~ -20:1: syntax error, unexpected `end', expecting end-of-input -...f true puts 'Hello, World!' end</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>20:1: syntax error, unexpected local variable or method, expecting `then' or ';' or '\n'</span></span> +<span class="line"><span>if true puts 'Hello, World!' end</span></span> +<span class="line"><span> ^~~~</span></span> +<span class="line"><span>20:1: syntax error, unexpected `end', expecting end-of-input</span></span> +<span class="line"><span>...f true puts 'Hello, World!' end</span></span></code></pre> + </div> <p> 二つ目のメッセージは無視して一つ目を読むと、<code>then</code> か <code>;</code> か改行が来るはずのところ変数だかメソッドだかが現れたことによりエラーとなっているようだ。 @@ -141,8 +148,10 @@ if true puts 'Hello, World!' end ポイントは改行が <code>then</code> (や <code>;</code>) の代わりとなることである。<code>true</code> の後に改行を入れてみる。 </p> - <pre class="highlight" language="ruby"><code class="highlight"><span class="hljs-keyword">if</span> <span class="hljs-literal">true</span> -puts <span class="hljs-string">'Hello, World!'</span> <span class="hljs-keyword">end</span></code></pre> + <div class="codeblock" language="ruby"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">if</span><span style="color:#005CC5"> true</span></span> +<span class="line"><span style="color:#005CC5">puts</span><span style="color:#032F62"> 'Hello, World!'</span><span style="color:#D73A49"> end</span></span></code></pre> + </div> <p> 無事 Hello, World! と出力されるようになった。 @@ -155,21 +164,27 @@ puts <span class="hljs-string">'Hello, World!'</span> <span class="hlj なぜ <code>then</code> や <code>;</code> や改行 (以下 「<code>then</code> 等」) が必要なのだろうか。次の例を見てほしい: </p> - <pre class="highlight" language="ruby"><code class="highlight"><span class="hljs-keyword">if</span> a b <span class="hljs-keyword">end</span></code></pre> + <div class="codeblock" language="ruby"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">if</span><span style="color:#24292E"> a b </span><span style="color:#D73A49">end</span></span></code></pre> + </div> <p> <code>then</code> も <code>;</code> も改行もないのでエラーになるが、これは条件式がどこまで続いているのかわからないためだ。この例は二通りに解釈できる。 </p> - <pre class="highlight" language="ruby"><code class="highlight"><span class="hljs-comment"># a という変数かメソッドの評価結果が truthy なら b という変数かメソッドを評価</span> -<span class="hljs-keyword">if</span> a <span class="hljs-keyword">then</span> -b -<span class="hljs-keyword">end</span></code></pre> + <div class="codeblock" language="ruby"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D"># a という変数かメソッドの評価結果が truthy なら b という変数かメソッドを評価</span></span> +<span class="line"><span style="color:#D73A49">if</span><span style="color:#24292E"> a </span><span style="color:#D73A49">then</span></span> +<span class="line"><span style="color:#24292E">b</span></span> +<span class="line"><span style="color:#D73A49">end</span></span></code></pre> + </div> - <pre class="highlight" language="ruby"><code class="highlight"><span class="hljs-comment"># a というメソッドに b という変数かメソッドの評価結果を渡して呼び出し、</span> -<span class="hljs-comment"># その結果が truthy なら何もしない</span> -<span class="hljs-keyword">if</span> a(b) <span class="hljs-keyword">then</span> -<span class="hljs-keyword">end</span></code></pre> + <div class="codeblock" language="ruby"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D"># a というメソッドに b という変数かメソッドの評価結果を渡して呼び出し、</span></span> +<span class="line"><span style="color:#6A737D"># その結果が truthy なら何もしない</span></span> +<span class="line"><span style="color:#D73A49">if</span><span style="color:#6F42C1"> a</span><span style="color:#24292E">(b) </span><span style="color:#D73A49">then</span></span> +<span class="line"><span style="color:#D73A49">end</span></span></code></pre> + </div> <p> <code>then</code> 等はこの曖昧性を排除するためにあり、条件式は <code>if</code> から <code>then</code> 等までの間にある、ということを明確にする。 C系の <code>if</code> 後に来る <code>(</code>/<code>)</code> や、Python の <code>:</code>、Rust/Go/Swift などの <code>{</code> も同じ役割を持つ。 @@ -190,39 +205,43 @@ b <a href="https://github.com/ruby/ruby/blob/221ca0f8281d39f0dfdfe13b2448875384bbf735/parse.y#L3961-L3986" rel="noreferrer" target="_blank">https://github.com/ruby/ruby/blob/221ca0f8281d39f0dfdfe13b2448875384bbf735/parse.y#L3961-L3986</a> </p> - <pre class="highlight" language="yacc"><code>p_case_body : keyword_in -{ - SET_LEX_STATE(EXPR_BEG|EXPR_LABEL); - p->command_start = FALSE; - $<ctxt>1 = p->ctxt; - p->ctxt.in_kwarg = 1; - $<tbl>$ = push_pvtbl(p); -} -{ - $<tbl>$ = push_pktbl(p); -} -p_top_expr then -{ - pop_pktbl(p, $<tbl>3); - pop_pvtbl(p, $<tbl>2); - p->ctxt.in_kwarg = $<ctxt>1.in_kwarg; -} -compstmt -p_cases -{ - /*%%%*/ - $$ = NEW_IN($4, $7, $8, &@$); - /*% %*/ - /*% ripper: in!($4, $7, escape_Qundef($8)) %*/ -} -;</code></pre> + <div class="codeblock" language="yacc"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>p_case_body : keyword_in</span></span> +<span class="line"><span>{</span></span> +<span class="line"><span> SET_LEX_STATE(EXPR_BEG|EXPR_LABEL);</span></span> +<span class="line"><span> p->command_start = FALSE;</span></span> +<span class="line"><span> $<ctxt>1 = p->ctxt;</span></span> +<span class="line"><span> p->ctxt.in_kwarg = 1;</span></span> +<span class="line"><span> $<tbl>$ = push_pvtbl(p);</span></span> +<span class="line"><span>}</span></span> +<span class="line"><span>{</span></span> +<span class="line"><span> $<tbl>$ = push_pktbl(p);</span></span> +<span class="line"><span>}</span></span> +<span class="line"><span>p_top_expr then</span></span> +<span class="line"><span>{</span></span> +<span class="line"><span> pop_pktbl(p, $<tbl>3);</span></span> +<span class="line"><span> pop_pvtbl(p, $<tbl>2);</span></span> +<span class="line"><span> p->ctxt.in_kwarg = $<ctxt>1.in_kwarg;</span></span> +<span class="line"><span>}</span></span> +<span class="line"><span>compstmt</span></span> +<span class="line"><span>p_cases</span></span> +<span class="line"><span>{</span></span> +<span class="line"><span> /*%%%*/</span></span> +<span class="line"><span> $$ = NEW_IN($4, $7, $8, &@$);</span></span> +<span class="line"><span> /*% %*/</span></span> +<span class="line"><span> /*% ripper: in!($4, $7, escape_Qundef($8)) %*/</span></span> +<span class="line"><span>}</span></span> +<span class="line"><span>;</span></span></code></pre> + </div> <p> 簡略版: </p> - <pre class="highlight" language="yacc"><code>p_case_body : keyword_in p_top_expr then compstmt p_cases -;</code></pre> + <div class="codeblock" language="yacc"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>p_case_body : keyword_in p_top_expr then compstmt p_cases</span></span> +<span class="line"><span>;</span></span></code></pre> + </div> <p> ここで、<code>keyword_in</code> は文字通り <code>in</code>、<code>p_top_expr</code> はいわゆるパターン、<code>then</code> は <code>then</code> キーワードのことではなく、この記事で <code>then</code> 等と呼んでいるもの、つまり <code>then</code> キーワード、<code>;</code>、改行のいずれかである。 @@ -232,36 +251,40 @@ p_cases これにより、<code>case</code> - <code>when</code> による従来の構文と同じように、<code>then</code> 等をパターンの後ろに挿入すればよいことがわかった。つまり次の3通りのいずれかになる: </p> - <pre class="highlight" language="ruby"><code class="highlight"><span class="hljs-keyword">case</span> x -<span class="hljs-keyword">in</span> <span class="hljs-number">1</span> <span class="hljs-keyword">then</span> a -<span class="hljs-keyword">in</span> <span class="hljs-number">2</span> <span class="hljs-keyword">then</span> b -<span class="hljs-keyword">in</span> <span class="hljs-number">3</span> <span class="hljs-keyword">then</span> c -<span class="hljs-keyword">end</span> - -<span class="hljs-keyword">case</span> x -<span class="hljs-keyword">in</span> <span class="hljs-number">1</span> - a -<span class="hljs-keyword">in</span> <span class="hljs-number">2</span> - b -<span class="hljs-keyword">in</span> <span class="hljs-number">3</span> - c -<span class="hljs-keyword">end</span> - -<span class="hljs-keyword">case</span> x -<span class="hljs-keyword">in</span> <span class="hljs-number">1</span>; a -<span class="hljs-keyword">in</span> <span class="hljs-number">2</span>; b -<span class="hljs-keyword">in</span> <span class="hljs-number">3</span>; c -<span class="hljs-keyword">end</span></code></pre> + <div class="codeblock" language="ruby"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">case</span><span style="color:#24292E"> x</span></span> +<span class="line"><span style="color:#D73A49">in</span><span style="color:#005CC5"> 1</span><span style="color:#D73A49"> then</span><span style="color:#24292E"> a</span></span> +<span class="line"><span style="color:#D73A49">in</span><span style="color:#005CC5"> 2</span><span style="color:#D73A49"> then</span><span style="color:#24292E"> b</span></span> +<span class="line"><span style="color:#D73A49">in</span><span style="color:#005CC5"> 3</span><span style="color:#D73A49"> then</span><span style="color:#24292E"> c</span></span> +<span class="line"><span style="color:#D73A49">end</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">case</span><span style="color:#24292E"> x</span></span> +<span class="line"><span style="color:#D73A49">in</span><span style="color:#005CC5"> 1</span></span> +<span class="line"><span style="color:#24292E"> a</span></span> +<span class="line"><span style="color:#D73A49">in</span><span style="color:#005CC5"> 2</span></span> +<span class="line"><span style="color:#24292E"> b</span></span> +<span class="line"><span style="color:#D73A49">in</span><span style="color:#005CC5"> 3</span></span> +<span class="line"><span style="color:#24292E"> c</span></span> +<span class="line"><span style="color:#D73A49">end</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">case</span><span style="color:#24292E"> x</span></span> +<span class="line"><span style="color:#D73A49">in</span><span style="color:#005CC5"> 1</span><span style="color:#24292E">; a</span></span> +<span class="line"><span style="color:#D73A49">in</span><span style="color:#005CC5"> 2</span><span style="color:#24292E">; b</span></span> +<span class="line"><span style="color:#D73A49">in</span><span style="color:#005CC5"> 3</span><span style="color:#24292E">; c</span></span> +<span class="line"><span style="color:#D73A49">end</span></span></code></pre> + </div> <p> ところで、<code>p_top_expr</code> には <code>if</code> による guard clause が書けるので、その場合は <code>if</code> - <code>then</code> と似たような見た目になる。 </p> - <pre class="highlight" language="ruby"><code class="highlight"><span class="hljs-keyword">case</span> x -<span class="hljs-keyword">in</span> <span class="hljs-number">0</span> <span class="hljs-keyword">then</span> a -<span class="hljs-keyword">in</span> n <span class="hljs-keyword">if</span> n < <span class="hljs-number">0</span> <span class="hljs-keyword">then</span> b -<span class="hljs-keyword">in</span> n <span class="hljs-keyword">then</span> c -<span class="hljs-keyword">end</span></code></pre> + <div class="codeblock" language="ruby"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">case</span><span style="color:#24292E"> x</span></span> +<span class="line"><span style="color:#D73A49">in</span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> then</span><span style="color:#24292E"> a</span></span> +<span class="line"><span style="color:#D73A49">in</span><span style="color:#24292E"> n </span><span style="color:#D73A49">if</span><span style="color:#24292E"> n </span><span style="color:#D73A49"><</span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> then</span><span style="color:#24292E"> b</span></span> +<span class="line"><span style="color:#D73A49">in</span><span style="color:#24292E"> n </span><span style="color:#D73A49">then</span><span style="color:#24292E"> c</span></span> +<span class="line"><span style="color:#D73A49">end</span></span></code></pre> + </div> </section> <section id="section--outro"> diff --git a/vhosts/blog/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html b/vhosts/blog/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html index 69cfb8a4..4ae7f235 100644 --- a/vhosts/blog/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html +++ b/vhosts/blog/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>Rust のプリミティブ型はどこからやって来るか|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -73,26 +72,28 @@ Rust において、プリミティブ型の名前は予約語でない。したがって、次のコードは合法である。 </p> - <pre class="highlight" language="rust"><code class="highlight"><span class="hljs-meta">#![allow(non_camel_case_types)]</span> -<span class="hljs-meta">#![allow(dead_code)]</span> - -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">bool</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">char</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">i8</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">i16</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">i32</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">i64</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">i128</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">isize</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">u8</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">u16</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">u32</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">u64</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">u128</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">usize</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">f32</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">f64</span>; -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">str</span>;</code></pre> + <div class="codeblock" language="rust"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">#![allow(non_camel_case_types)]</span></span> +<span class="line"><span style="color:#24292E">#![allow(dead_code)]</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> bool</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> char</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> i8</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> i16</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> i32</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> i64</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> i128</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> isize</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> u8</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> u16</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> u32</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> u64</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> u128</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> usize</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> f32</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> f64</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> str</span><span style="color:#24292E">;</span></span></code></pre> + </div> <p> では、普段単に <code>bool</code> と書いたとき、この <code>bool</code> は一体どこから来ているのか。rustc のソースを追ってみた。 @@ -127,60 +128,66 @@ <code>rustc</code> はセルフホストされている (= <code>rustc</code> 自身が Rust で書かれている) ので、<code>bool</code> や <code>char</code> などで適当に検索をかけてもノイズが多すぎて話にならない。しかし、お誂え向きなことに <code>i128</code>/<code>u128</code> というコンパイラ自身が使うことがなさそうな型が存在するのでこれを使って <code>git grep</code> してみる。 </p> - <pre class="highlight"><code>$ git grep "\bi128\b" | wc # i128 -165 1069 15790 - -$ git grep "\bu128\b" | wc # u128 -293 2127 26667 - -$ git grep "\bbool\b" | wc # cf. bool の結果 -3563 23577 294659</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ git grep "\bi128\b" | wc # i128</span></span> +<span class="line"><span>165 1069 15790</span></span> +<span class="line"><span></span></span> +<span class="line"><span>$ git grep "\bu128\b" | wc # u128</span></span> +<span class="line"><span>293 2127 26667</span></span> +<span class="line"><span></span></span> +<span class="line"><span>$ git grep "\bbool\b" | wc # cf. bool の結果</span></span> +<span class="line"><span>3563 23577 294659</span></span></code></pre> + </div> <p> 165 程度であれば探すことができそうだ。今回は、クレート名を見ておおよその当たりをつけた。 </p> - <pre class="highlight"><code>$ git grep "\bi128\b" -... -rustc_resolve/src/lib.rs: table.insert(sym::i128, Int(IntTy::I128)); -...</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ git grep "\bi128\b"</span></span> +<span class="line"><span>...</span></span> +<span class="line"><span>rustc_resolve/src/lib.rs: table.insert(sym::i128, Int(IntTy::I128));</span></span> +<span class="line"><span>...</span></span></code></pre> + </div> <p> <code>rustc_resolve</code> というのはいかにも名前解決を担いそうなクレート名である。該当箇所を見てみる。 </p> - <pre class="highlight" language="rust"><code class="highlight"><span class="hljs-comment">/// Interns the names of the primitive types.</span> -<span class="hljs-comment">///</span> -<span class="hljs-comment">/// All other types are defined somewhere and possibly imported, but the primitive ones need</span> -<span class="hljs-comment">/// special handling, since they have no place of origin.</span> -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">PrimitiveTypeTable</span> { - primitive_types: FxHashMap<Symbol, PrimTy>, -} - -<span class="hljs-keyword">impl</span> <span class="hljs-title class_">PrimitiveTypeTable</span> { - <span class="hljs-keyword">fn</span> <span class="hljs-title function_">new</span>() <span class="hljs-punctuation">-></span> PrimitiveTypeTable { - <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut </span><span class="hljs-variable">table</span> = FxHashMap::<span class="hljs-title function_ invoke__">default</span>(); - - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">bool</span>, Bool); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">char</span>, Char); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">f32</span>, <span class="hljs-title function_ invoke__">Float</span>(FloatTy::F32)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">f64</span>, <span class="hljs-title function_ invoke__">Float</span>(FloatTy::F64)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">isize</span>, <span class="hljs-title function_ invoke__">Int</span>(IntTy::Isize)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">i8</span>, <span class="hljs-title function_ invoke__">Int</span>(IntTy::I8)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">i16</span>, <span class="hljs-title function_ invoke__">Int</span>(IntTy::I16)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">i32</span>, <span class="hljs-title function_ invoke__">Int</span>(IntTy::I32)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">i64</span>, <span class="hljs-title function_ invoke__">Int</span>(IntTy::I64)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">i128</span>, <span class="hljs-title function_ invoke__">Int</span>(IntTy::I128)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">str</span>, Str); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">usize</span>, <span class="hljs-title function_ invoke__">Uint</span>(UintTy::Usize)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">u8</span>, <span class="hljs-title function_ invoke__">Uint</span>(UintTy::U8)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">u16</span>, <span class="hljs-title function_ invoke__">Uint</span>(UintTy::U16)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">u32</span>, <span class="hljs-title function_ invoke__">Uint</span>(UintTy::U32)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">u64</span>, <span class="hljs-title function_ invoke__">Uint</span>(UintTy::U64)); - table.<span class="hljs-title function_ invoke__">insert</span>(sym::<span class="hljs-type">u128</span>, <span class="hljs-title function_ invoke__">Uint</span>(UintTy::U128)); - <span class="hljs-keyword">Self</span> { primitive_types: table } - } -}</code></pre> + <div class="codeblock" language="rust"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D">/// Interns the names of the primitive types.</span></span> +<span class="line"><span style="color:#6A737D">///</span></span> +<span class="line"><span style="color:#6A737D">/// All other types are defined somewhere and possibly imported, but the primitive ones need</span></span> +<span class="line"><span style="color:#6A737D">/// special handling, since they have no place of origin.</span></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> PrimitiveTypeTable</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> primitive_types</span><span style="color:#D73A49">:</span><span style="color:#6F42C1"> FxHashMap</span><span style="color:#24292E"><</span><span style="color:#6F42C1">Symbol</span><span style="color:#24292E">, </span><span style="color:#6F42C1">PrimTy</span><span style="color:#24292E">>,</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">impl</span><span style="color:#6F42C1"> PrimitiveTypeTable</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> fn</span><span style="color:#6F42C1"> new</span><span style="color:#24292E">() </span><span style="color:#D73A49">-></span><span style="color:#6F42C1"> PrimitiveTypeTable</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> let</span><span style="color:#D73A49"> mut</span><span style="color:#24292E"> table </span><span style="color:#D73A49">=</span><span style="color:#6F42C1"> FxHashMap</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">default</span><span style="color:#24292E">();</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">bool</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Bool</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">char</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Char</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">f32</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Float</span><span style="color:#24292E">(</span><span style="color:#6F42C1">FloatTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">F32</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">f64</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Float</span><span style="color:#24292E">(</span><span style="color:#6F42C1">FloatTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">F64</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">isize</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Int</span><span style="color:#24292E">(</span><span style="color:#6F42C1">IntTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">Isize</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">i8</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Int</span><span style="color:#24292E">(</span><span style="color:#6F42C1">IntTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">I8</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">i16</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Int</span><span style="color:#24292E">(</span><span style="color:#6F42C1">IntTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">I16</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">i32</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Int</span><span style="color:#24292E">(</span><span style="color:#6F42C1">IntTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">I32</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">i64</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Int</span><span style="color:#24292E">(</span><span style="color:#6F42C1">IntTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">I64</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">i128</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Int</span><span style="color:#24292E">(</span><span style="color:#6F42C1">IntTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">I128</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">str</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Str</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">usize</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Uint</span><span style="color:#24292E">(</span><span style="color:#6F42C1">UintTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">Usize</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">u8</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Uint</span><span style="color:#24292E">(</span><span style="color:#6F42C1">UintTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">U8</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">u16</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Uint</span><span style="color:#24292E">(</span><span style="color:#6F42C1">UintTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">U16</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">u32</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Uint</span><span style="color:#24292E">(</span><span style="color:#6F42C1">UintTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">U32</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">u64</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Uint</span><span style="color:#24292E">(</span><span style="color:#6F42C1">UintTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">U64</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E"> table</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">insert</span><span style="color:#24292E">(</span><span style="color:#6F42C1">sym</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">u128</span><span style="color:#24292E">, </span><span style="color:#6F42C1">Uint</span><span style="color:#24292E">(</span><span style="color:#6F42C1">UintTy</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">U128</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#005CC5"> Self</span><span style="color:#24292E"> { primitive_types</span><span style="color:#D73A49">:</span><span style="color:#24292E"> table }</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> これは初めに列挙したプリミティブ型の一覧と一致している。doc comment にも、 @@ -196,27 +203,29 @@ rustc_resolve/src/lib.rs: table.insert(sym::i128, Int(IntTy::I128)); とある。次はこの struct の使用箇所を追う。追うと言っても使われている箇所は次の一箇所しかない。なお説明に不要な箇所は大きく削っている。 </p> - <pre class="highlight" language="rust"><code class="highlight"><span class="hljs-comment">/// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.</span> -<span class="hljs-comment">/// (略)</span> -<span class="hljs-keyword">fn</span> <span class="hljs-title function_">resolve_ident_in_lexical_scope</span>( - &<span class="hljs-keyword">mut</span> <span class="hljs-keyword">self</span>, - <span class="hljs-keyword">mut</span> ident: Ident, - ns: Namespace, - <span class="hljs-comment">// (略)</span> -) <span class="hljs-punctuation">-></span> <span class="hljs-type">Option</span><LexicalScopeBinding<<span class="hljs-symbol">'a</span>>> { - <span class="hljs-comment">// (略)</span> - - <span class="hljs-keyword">if</span> ns == TypeNS { - <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> <span class="hljs-variable">Some</span>(prim_ty) = <span class="hljs-keyword">self</span>.primitive_type_table.primitive_types.<span class="hljs-title function_ invoke__">get</span>(&ident.name) { - <span class="hljs-keyword">let</span> <span class="hljs-variable">binding</span> = - (Res::<span class="hljs-title function_ invoke__">PrimTy</span>(*prim_ty), ty::Visibility::Public, DUMMY_SP, ExpnId::<span class="hljs-title function_ invoke__">root</span>()) - .<span class="hljs-title function_ invoke__">to_name_binding</span>(<span class="hljs-keyword">self</span>.arenas); - <span class="hljs-keyword">return</span> <span class="hljs-title function_ invoke__">Some</span>(LexicalScopeBinding::<span class="hljs-title function_ invoke__">Item</span>(binding)); - } - } - - <span class="hljs-literal">None</span> -}</code></pre> + <div class="codeblock" language="rust"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D">/// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.</span></span> +<span class="line"><span style="color:#6A737D">/// (略)</span></span> +<span class="line"><span style="color:#D73A49">fn</span><span style="color:#6F42C1"> resolve_ident_in_lexical_scope</span><span style="color:#24292E">(</span></span> +<span class="line"><span style="color:#D73A49"> &mut</span><span style="color:#005CC5"> self</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#D73A49"> mut</span><span style="color:#24292E"> ident</span><span style="color:#D73A49">:</span><span style="color:#6F42C1"> Ident</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E"> ns</span><span style="color:#D73A49">:</span><span style="color:#6F42C1"> Namespace</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#6A737D"> // (略)</span></span> +<span class="line"><span style="color:#24292E">) </span><span style="color:#D73A49">-></span><span style="color:#6F42C1"> Option</span><span style="color:#24292E"><</span><span style="color:#6F42C1">LexicalScopeBinding</span><span style="color:#24292E"><'</span><span style="color:#6F42C1">a</span><span style="color:#24292E">>> {</span></span> +<span class="line"><span style="color:#6A737D"> // (略)</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> ns </span><span style="color:#D73A49">==</span><span style="color:#6F42C1"> TypeNS</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#D73A49"> let</span><span style="color:#6F42C1"> Some</span><span style="color:#24292E">(prim_ty) </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> self</span><span style="color:#D73A49">.</span><span style="color:#24292E">primitive_type_table</span><span style="color:#D73A49">.</span><span style="color:#24292E">primitive_types</span><span style="color:#D73A49">.</span><span style="color:#6F42C1">get</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">ident</span><span style="color:#D73A49">.</span><span style="color:#24292E">name) {</span></span> +<span class="line"><span style="color:#D73A49"> let</span><span style="color:#24292E"> binding </span><span style="color:#D73A49">=</span></span> +<span class="line"><span style="color:#24292E"> (</span><span style="color:#6F42C1">Res</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">PrimTy</span><span style="color:#24292E">(</span><span style="color:#D73A49">*</span><span style="color:#24292E">prim_ty), </span><span style="color:#6F42C1">ty</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">Visibility</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">Public</span><span style="color:#24292E">, </span><span style="color:#005CC5">DUMMY_SP</span><span style="color:#24292E">, </span><span style="color:#6F42C1">ExpnId</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">root</span><span style="color:#24292E">())</span></span> +<span class="line"><span style="color:#D73A49"> .</span><span style="color:#6F42C1">to_name_binding</span><span style="color:#24292E">(</span><span style="color:#005CC5">self</span><span style="color:#D73A49">.</span><span style="color:#24292E">arenas);</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#6F42C1"> Some</span><span style="color:#24292E">(</span><span style="color:#6F42C1">LexicalScopeBinding</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">Item</span><span style="color:#24292E">(binding));</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6F42C1"> None</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> 関数名や doc comment が示している通り、この関数は識別子 (identifier, ident) を現在のレキシカルスコープ内で解決 (resolve) する。<code>if ns == TypeNS</code> のブロック内では、<code>primitive_type_table</code> (上記の <code>PrimitiveTypeTable::new()</code> で作られた変数) に含まれている識別子 (<code>bool</code>、<code>i32</code> など) かどうか判定し、そうであればそれに紐づけられたプリミティブ型を返している。 @@ -234,13 +243,15 @@ rustc_resolve/src/lib.rs: table.insert(sym::i128, Int(IntTy::I128)); 動作がわかったところで、例として次のコードを考える。 </p> - <pre class="highlight" language="rust"><code class="highlight"><span class="hljs-meta">#![allow(non_camel_case_types)]</span> - -<span class="hljs-keyword">struct</span> <span class="hljs-title class_">bool</span>; - -<span class="hljs-keyword">fn</span> <span class="hljs-title function_">main</span>() { - <span class="hljs-keyword">let</span> <span class="hljs-variable">_</span>: <span class="hljs-type">bool</span> = <span class="hljs-type">bool</span>; -}</code></pre> + <div class="codeblock" language="rust"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">#![allow(non_camel_case_types)]</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">struct</span><span style="color:#6F42C1"> bool</span><span style="color:#24292E">;</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">fn</span><span style="color:#6F42C1"> main</span><span style="color:#24292E">() {</span></span> +<span class="line"><span style="color:#D73A49"> let</span><span style="color:#24292E"> _</span><span style="color:#D73A49">:</span><span style="color:#6F42C1"> bool</span><span style="color:#D73A49"> =</span><span style="color:#6F42C1"> bool</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> ここで <code>main()</code> の <code>bool</code> は <code>struct bool</code> として解決される。なぜなら、プリミティブ型の判定をする前に <code>bool</code> という名前の別の型が見つかるからだ。 diff --git a/vhosts/blog/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html b/vhosts/blog/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html index 72c04ee1..ddf70cae 100644 --- a/vhosts/blog/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html +++ b/vhosts/blog/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>【Vim】 autocmd events の BufWrite/BufWritePre の違い|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -124,24 +123,30 @@ <a href="https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86" rel="noreferrer" target="_blank">https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86</a> </p> - <pre class="highlight" language="c"><code class="highlight">{<span class="hljs-string">"BufAdd"</span>, EVENT_BUFADD}, -{<span class="hljs-string">"BufCreate"</span>, EVENT_BUFADD},</code></pre> + <div class="codeblock" language="c"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">{</span><span style="color:#032F62">"BufAdd"</span><span style="color:#24292E">, EVENT_BUFADD},</span></span> +<span class="line"><span style="color:#24292E">{</span><span style="color:#032F62">"BufCreate"</span><span style="color:#24292E">, EVENT_BUFADD},</span></span></code></pre> + </div> <p> <a href="https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97" rel="noreferrer" target="_blank">https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97</a> </p> - <pre class="highlight" language="c"><code class="highlight">{<span class="hljs-string">"BufRead"</span>, EVENT_BUFREADPOST}, -{<span class="hljs-string">"BufReadCmd"</span>, EVENT_BUFREADCMD}, -{<span class="hljs-string">"BufReadPost"</span>, EVENT_BUFREADPOST},</code></pre> + <div class="codeblock" language="c"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">{</span><span style="color:#032F62">"BufRead"</span><span style="color:#24292E">, EVENT_BUFREADPOST},</span></span> +<span class="line"><span style="color:#24292E">{</span><span style="color:#032F62">"BufReadCmd"</span><span style="color:#24292E">, EVENT_BUFREADCMD},</span></span> +<span class="line"><span style="color:#24292E">{</span><span style="color:#032F62">"BufReadPost"</span><span style="color:#24292E">, EVENT_BUFREADPOST},</span></span></code></pre> + </div> <p> <a href="https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105" rel="noreferrer" target="_blank">https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105</a> </p> - <pre class="highlight" language="c"><code class="highlight">{<span class="hljs-string">"BufWrite"</span>, EVENT_BUFWRITEPRE}, -{<span class="hljs-string">"BufWritePost"</span>, EVENT_BUFWRITEPOST}, -{<span class="hljs-string">"BufWritePre"</span>, EVENT_BUFWRITEPRE},</code></pre> + <div class="codeblock" language="c"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">{</span><span style="color:#032F62">"BufWrite"</span><span style="color:#24292E">, EVENT_BUFWRITEPRE},</span></span> +<span class="line"><span style="color:#24292E">{</span><span style="color:#032F62">"BufWritePost"</span><span style="color:#24292E">, EVENT_BUFWRITEPOST},</span></span> +<span class="line"><span style="color:#24292E">{</span><span style="color:#032F62">"BufWritePre"</span><span style="color:#24292E">, EVENT_BUFWRITEPRE},</span></span></code></pre> + </div> </section> <section id="section--code-reading--neovim"> @@ -154,20 +159,24 @@ <a href="https://github.com/neovim/neovim/blob/71d4f5851f068eeb432af34850dddda8cc1c71e3/src/nvim/auevents.lua#L119-L124" rel="noreferrer" target="_blank">https://github.com/neovim/neovim/blob/71d4f5851f068eeb432af34850dddda8cc1c71e3/src/nvim/auevents.lua#L119-L124</a> </p> - <pre class="highlight" language="lua"><code class="highlight">aliases = { -BufCreate = <span class="hljs-string">'BufAdd'</span>, -BufRead = <span class="hljs-string">'BufReadPost'</span>, -BufWrite = <span class="hljs-string">'BufWritePre'</span>, -FileEncoding = <span class="hljs-string">'EncodingChanged'</span>, -},</code></pre> + <div class="codeblock" language="lua"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">aliases </span><span style="color:#D73A49">=</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> BufCreate </span><span style="color:#D73A49">=</span><span style="color:#032F62"> 'BufAdd'</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E"> BufRead </span><span style="color:#D73A49">=</span><span style="color:#032F62"> 'BufReadPost'</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E"> BufWrite </span><span style="color:#D73A49">=</span><span style="color:#032F62"> 'BufWritePre'</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E"> FileEncoding </span><span style="color:#D73A49">=</span><span style="color:#032F62"> 'EncodingChanged'</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E">},</span></span></code></pre> + </div> <p> ところで、上では取り上げなかった <code>FileEncoding</code> だが、これは <code>:help FileEncoding</code> にしっかりと書いてある。 </p> - <pre class="highlight"><code> *FileEncoding* -FileEncoding Obsolete. It still works and is equivalent - to |EncodingChanged|.</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span> *FileEncoding*</span></span> +<span class="line"><span>FileEncoding Obsolete. It still works and is equivalent</span></span> +<span class="line"><span> to |EncodingChanged|.</span></span></code></pre> + </div> </section> </section> diff --git a/vhosts/blog/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html b/vhosts/blog/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html index 00a6265b..afee803f 100644 --- a/vhosts/blog/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html +++ b/vhosts/blog/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>Vimで選択した行の順番を入れ替える|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -69,11 +68,13 @@ <section id="section--tl-dr"> <h2><a href="#section--tl-dr">TL; DR</a></h2> - <pre class="highlight" language="vim"><code class="highlight"><span class="hljs-comment">" License: Public Domain</span> - -command! -bar -<span class="hljs-built_in">range</span>=% - \ Reverse - \ keeppatterns <span class="hljs-symbol"><line1></span>,<span class="hljs-symbol"><line2></span>g/^/<span class="hljs-keyword">m</span><span class="hljs-symbol"><line1></span>-<span class="hljs-number">1</span></code></pre> + <div class="codeblock" language="vim"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D">" License: Public Domain</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">command!</span><span style="color:#24292E"> -bar -</span><span style="color:#D73A49">range=</span><span style="color:#24292E">%</span></span> +<span class="line"><span style="color:#D73A49"> \</span><span style="color:#24292E"> Reverse</span></span> +<span class="line"><span style="color:#D73A49"> \</span><span style="color:#24292E"> keeppatterns <line1>,<line2>g</span><span style="color:#032F62">/^/</span><span style="color:#24292E">m<line1>-</span><span style="color:#005CC5">1</span></span></code></pre> + </div> </section> <section id="section--version"> @@ -142,9 +143,11 @@ command! -bar -<span class="hljs-built_in">range</span>=% なお、<code>:g/^/m0</code> は全ての行を入れ替えるが、<code>:N,Mg/^/mN-1</code> とすることで N行目から M行目を処理範囲とするよう拡張できる。手でこれを入力するわけにはいかないので、次のようなコマンドを用意する。 </p> - <pre class="highlight" language="vim"><code class="highlight">command! -bar -<span class="hljs-built_in">range</span>=% - \ Reverse - \ <span class="hljs-symbol"><line1></span>,<span class="hljs-symbol"><line2></span>g/^/<span class="hljs-keyword">m</span><span class="hljs-symbol"><line1></span>-<span class="hljs-number">1</span></code></pre> + <div class="codeblock" language="vim"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">command!</span><span style="color:#24292E"> -bar -</span><span style="color:#D73A49">range=</span><span style="color:#24292E">%</span></span> +<span class="line"><span style="color:#D73A49"> \</span><span style="color:#24292E"> Reverse</span></span> +<span class="line"><span style="color:#D73A49"> \</span><span style="color:#24292E"> <line1>,<line2>g</span><span style="color:#032F62">/^/</span><span style="color:#24292E">m<line1>-</span><span style="color:#005CC5">1</span></span></code></pre> + </div> <p> これは望みの動作をするが、実際に実行してみると全行がハイライトされてしまう。次節で詳細を述べる。 @@ -177,13 +180,15 @@ command! -bar -<span class="hljs-built_in">range</span>=% 前述した <code>:Reverse</code> コマンドの定義を少し変えて、次のようにする: </p> - <pre class="highlight" language="vim"><code class="highlight"><span class="hljs-keyword">function!</span> <span class="hljs-title">s</span>:reverse_lines<span class="hljs-params">(from, to)</span> abort - <span class="hljs-keyword">execute</span> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"%d,%dg/^/m%d"</span>, <span class="hljs-variable">a:from</span>, <span class="hljs-variable">a:to</span>, <span class="hljs-variable">a:from</span> - <span class="hljs-number">1</span>) -<span class="hljs-keyword">endfunction</span> - -command! -bar -<span class="hljs-built_in">range</span>=% - \ Reverse - \ <span class="hljs-keyword">call</span> <span class="hljs-symbol"><SID></span>reverse_lines(<span class="hljs-symbol"><line1></span>, <span class="hljs-symbol"><line2></span>)</code></pre> + <div class="codeblock" language="vim"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">function!</span><span style="color:#6F42C1"> s:reverse_lines</span><span style="color:#24292E">(from, </span><span style="color:#005CC5">to</span><span style="color:#24292E">) </span><span style="color:#D73A49">abort</span></span> +<span class="line"><span style="color:#005CC5"> execute</span><span style="color:#6F42C1"> printf</span><span style="color:#24292E">(</span><span style="color:#032F62">"%d,%dg/^/m%d"</span><span style="color:#24292E">, a:from, a:to, a:from</span><span style="color:#D73A49"> - </span><span style="color:#005CC5">1</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#D73A49">endfunction</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">command!</span><span style="color:#24292E"> -bar -</span><span style="color:#D73A49">range=</span><span style="color:#24292E">%</span></span> +<span class="line"><span style="color:#D73A49"> \</span><span style="color:#24292E"> Reverse</span></span> +<span class="line"><span style="color:#D73A49"> \</span><span style="color:#D73A49"> call</span><span style="color:#24292E"> <</span><span style="color:#005CC5">SID</span><span style="color:#24292E">></span><span style="color:#6F42C1">reverse_lines</span><span style="color:#24292E">(<line1>, <line2>)</span></span></code></pre> + </div> <p> 実行しているコマンドが変わったわけではないが、関数呼び出しを経由するようにした。これだけで前述の問題が解決する。 @@ -234,9 +239,11 @@ command! -bar -<span class="hljs-built_in">range</span>=% </p> </blockquote> - <pre class="highlight" language="vim"><code class="highlight">command! -bar -<span class="hljs-built_in">range</span>=% - \ Reverse - \ keeppatterns <span class="hljs-symbol"><line1></span>,<span class="hljs-symbol"><line2></span>g/^/<span class="hljs-keyword">m</span><span class="hljs-symbol"><line1></span>-<span class="hljs-number">1</span></code></pre> + <div class="codeblock" language="vim"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">command!</span><span style="color:#24292E"> -bar -</span><span style="color:#D73A49">range=</span><span style="color:#24292E">%</span></span> +<span class="line"><span style="color:#D73A49"> \</span><span style="color:#24292E"> Reverse</span></span> +<span class="line"><span style="color:#D73A49"> \</span><span style="color:#24292E"> keeppatterns <line1>,<line2>g</span><span style="color:#032F62">/^/</span><span style="color:#24292E">m<line1>-</span><span style="color:#005CC5">1</span></span></code></pre> + </div> <p> まさにこのための Exコマンド、<code>:keeppatterns</code> が存在する。<code>:keeppatterns {command}</code> のように使い、読んで字の如く、後ろに続く Exコマンドを「現在の検索パターンを保ったまま」実行する。はるかに分かりやすく意図を表現できる。 diff --git a/vhosts/blog/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html b/vhosts/blog/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html index b4875558..3469e8b1 100644 --- a/vhosts/blog/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html +++ b/vhosts/blog/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>PHPerKaigi 2022 トークン問題の解説|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -84,75 +83,77 @@ ソースコードはこちら。実行には PHP 8.1 以上が必要なので注意。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> - -<span class="hljs-keyword">declare</span>(strict_types=<span class="hljs-number">0O1</span>); - -<span class="hljs-keyword">namespace</span> <span class="hljs-title class_">Dgcircus</span>\<span class="hljs-title class_">PHPerKaigi</span>\<span class="hljs-title class_">Y2022</span>; - -<span class="hljs-comment">/** - * <span class="hljs-doctag">@todo</span> - * Run this program to acquire a PHPer token. - */</span> - -https:<span class="hljs-comment">//creativecommons.org/publicdomain/zero/1.0/</span> - -\<span class="hljs-title function_ invoke__">error_reporting</span>(~+!<span class="hljs-string">'We are hiring!'</span>); - -<span class="hljs-variable">$z</span> = <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$f</span></span>) =></span> (<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$x</span></span>) =></span> <span class="hljs-variable">$f</span>(<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params">...<span class="hljs-variable">$xs</span></span>) =></span> <span class="hljs-variable">$x</span>(<span class="hljs-variable">$x</span>)(...<span class="hljs-variable">$xs</span>)))(<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$x</span></span>) =></span> <span class="hljs-variable">$f</span>(<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params">...<span class="hljs-variable">$xs</span></span>) =></span> <span class="hljs-variable">$x</span>(<span class="hljs-variable">$x</span>)(...<span class="hljs-variable">$xs</span>))); -<span class="hljs-variable">$id</span> = \<span class="hljs-title function_ invoke__">spl_object_id</span>(...); -<span class="hljs-variable">$put</span> = <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$c</span></span>) =></span> \<span class="hljs-title function_ invoke__">printf</span>(<span class="hljs-string">'%c'</span>, <span class="hljs-variable">$c</span>); -<span class="hljs-variable">$mm</span> = <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$p</span>, <span class="hljs-variable">$n</span></span>) =></span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">\ArrayObject</span>(\<span class="hljs-title function_ invoke__">array_fill</span>(+!![], <span class="hljs-variable">$n</span>, <span class="hljs-variable">$p</span>)); - -$👉 = <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$m</span>, <span class="hljs-variable">$p</span>, <span class="hljs-variable">$b</span>, <span class="hljs-variable">$e</span>, <span class="hljs-variable">$mp</span>, <span class="hljs-variable">$pc</span></span>) =></span> [++<span class="hljs-variable">$mp</span>, ++<span class="hljs-variable">$pc</span>]; -$👈 = <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$m</span>, <span class="hljs-variable">$p</span>, <span class="hljs-variable">$b</span>, <span class="hljs-variable">$e</span>, <span class="hljs-variable">$mp</span>, <span class="hljs-variable">$pc</span></span>) =></span> [--<span class="hljs-variable">$mp</span>, ++<span class="hljs-variable">$pc</span>]; -$👍 = <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$m</span>, <span class="hljs-variable">$p</span>, <span class="hljs-variable">$b</span>, <span class="hljs-variable">$e</span>, <span class="hljs-variable">$mp</span>, <span class="hljs-variable">$pc</span></span>) =></span> [<span class="hljs-variable">$mp</span>, ++<span class="hljs-variable">$pc</span>, ++<span class="hljs-variable">$m</span>[<span class="hljs-variable">$mp</span>]]; -$👎 = <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$m</span>, <span class="hljs-variable">$p</span>, <span class="hljs-variable">$b</span>, <span class="hljs-variable">$e</span>, <span class="hljs-variable">$mp</span>, <span class="hljs-variable">$pc</span></span>) =></span> [<span class="hljs-variable">$mp</span>, ++<span class="hljs-variable">$pc</span>, --<span class="hljs-variable">$m</span>[<span class="hljs-variable">$mp</span>]]; -$📝 = <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$m</span>, <span class="hljs-variable">$p</span>, <span class="hljs-variable">$b</span>, <span class="hljs-variable">$e</span>, <span class="hljs-variable">$mp</span>, <span class="hljs-variable">$pc</span></span>) =></span> [<span class="hljs-variable">$mp</span>, ++<span class="hljs-variable">$pc</span>, <span class="hljs-variable">$put</span>(<span class="hljs-variable">$m</span>[<span class="hljs-variable">$mp</span>])]; -$🤡 = <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$m</span>, <span class="hljs-variable">$p</span>, <span class="hljs-variable">$b</span>, <span class="hljs-variable">$e</span>, <span class="hljs-variable">$mp</span>, <span class="hljs-variable">$pc</span></span>) =></span> <span class="hljs-keyword">match</span> (<span class="hljs-variable">$m</span>[<span class="hljs-variable">$mp</span>]) { - +!![] => [<span class="hljs-variable">$mp</span>, <span class="hljs-variable">$z</span>(<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$loop</span></span>) =></span> <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$pc</span>, <span class="hljs-variable">$n</span></span>) =></span> <span class="hljs-keyword">match</span> (<span class="hljs-variable">$id</span>(<span class="hljs-variable">$p</span>[<span class="hljs-variable">$pc</span>])) { - <span class="hljs-variable">$b</span> => <span class="hljs-variable">$loop</span>(++<span class="hljs-variable">$pc</span>, ++<span class="hljs-variable">$n</span>), - <span class="hljs-variable">$e</span> => <span class="hljs-variable">$n</span> === +!![] ? ++<span class="hljs-variable">$pc</span> : <span class="hljs-variable">$loop</span>(++<span class="hljs-variable">$pc</span>, --<span class="hljs-variable">$n</span>), - <span class="hljs-keyword">default</span> => <span class="hljs-variable">$loop</span>(++<span class="hljs-variable">$pc</span>, <span class="hljs-variable">$n</span>), - })(<span class="hljs-variable">$pc</span>, -![])], - <span class="hljs-keyword">default</span> => [<span class="hljs-variable">$mp</span>, ++<span class="hljs-variable">$pc</span>], -}; -$🎪 = <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$m</span>, <span class="hljs-variable">$p</span>, <span class="hljs-variable">$b</span>, <span class="hljs-variable">$e</span>, <span class="hljs-variable">$mp</span>, <span class="hljs-variable">$pc</span></span>) =></span> <span class="hljs-keyword">match</span> (<span class="hljs-variable">$m</span>[<span class="hljs-variable">$mp</span>]) { - +!![] => [<span class="hljs-variable">$mp</span>, ++<span class="hljs-variable">$pc</span>], - <span class="hljs-keyword">default</span> => [<span class="hljs-variable">$mp</span>, <span class="hljs-variable">$z</span>(<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$loop</span></span>) =></span> <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$pc</span>, <span class="hljs-variable">$n</span></span>) =></span> <span class="hljs-keyword">match</span> (<span class="hljs-variable">$id</span>(<span class="hljs-variable">$p</span>[<span class="hljs-variable">$pc</span>])) { - <span class="hljs-variable">$e</span> => <span class="hljs-variable">$loop</span>(--<span class="hljs-variable">$pc</span>, ++<span class="hljs-variable">$n</span>), - <span class="hljs-variable">$b</span> => <span class="hljs-variable">$n</span> === +!![] ? <span class="hljs-variable">$pc</span>+![] : <span class="hljs-variable">$loop</span>(--<span class="hljs-variable">$pc</span>, --<span class="hljs-variable">$n</span>), - <span class="hljs-keyword">default</span> => <span class="hljs-variable">$loop</span>(--<span class="hljs-variable">$pc</span>, <span class="hljs-variable">$n</span>), - })(<span class="hljs-variable">$pc</span>, -![])], -}; -$🐘 = <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$p</span></span>) =></span> <span class="hljs-variable">$z</span>(<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$loop</span></span>) =></span> <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$m</span>, <span class="hljs-variable">$p</span>, <span class="hljs-variable">$b</span>, <span class="hljs-variable">$e</span>, <span class="hljs-variable">$mp</span>, <span class="hljs-variable">$pc</span></span>) =></span> - <span class="hljs-keyword">isset</span>(<span class="hljs-variable">$p</span>[<span class="hljs-variable">$pc</span>]) && <span class="hljs-variable">$loop</span>(<span class="hljs-variable">$m</span>, <span class="hljs-variable">$p</span>, <span class="hljs-variable">$b</span>, <span class="hljs-variable">$e</span>, ...(<span class="hljs-variable">$p</span>[<span class="hljs-variable">$pc</span>](<span class="hljs-variable">$m</span>, <span class="hljs-variable">$p</span>, <span class="hljs-variable">$b</span>, <span class="hljs-variable">$e</span>, <span class="hljs-variable">$mp</span>, <span class="hljs-variable">$pc</span>))) -)(<span class="hljs-variable">$mm</span>(+!![], +(![].![])), <span class="hljs-variable">$p</span>, <span class="hljs-variable">$id</span>($🤡), <span class="hljs-variable">$id</span>($🎪), +!![], +!![]); - -$🐘([ - $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, - $🤡, - $👉, $👍, $👍, $👍, - $👉, $👍, $👍, $👍, $👍, $👍, - $👉, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, - $👉, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, - $👈, $👈, $👈, $👈, $👎, - $🎪, - $👉, $👍, $👍, $👍, $👍, $👍, $📝, - $👎, $👎, $📝, - $👉, $👎, $👎, $👎, $📝, - $👉, $👎, $👎, $👎, $📝, - $👎, $👎, $📝, - $👎, $📝, - $👈, $📝, - $👉, $👉, $👎, $👎, $📝, - $👍, $👍, $👍, $👍, $👍, $👍, $👍, $📝, - $👈, $👎, $👎, $👎, $👎, $📝, - $👈, $📝, - $👉, $👍, $👍, $📝, - $👉, $👎, $📝, - $👈, $📝, -]);</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">declare</span><span style="color:#24292E">(</span><span style="color:#005CC5">strict_types</span><span style="color:#D73A49">=</span><span style="color:#005CC5">0O1</span><span style="color:#24292E">);</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">namespace</span><span style="color:#6F42C1"> Dgcircus\PHPerKaigi\Y2022</span><span style="color:#24292E">;</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6A737D">/**</span></span> +<span class="line"><span style="color:#6A737D"> * </span><span style="color:#D73A49">@todo</span></span> +<span class="line"><span style="color:#6A737D"> * Run this program to acquire a PHPer token.</span></span> +<span class="line"><span style="color:#6A737D"> */</span></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5">https</span><span style="color:#D73A49">:</span><span style="color:#6A737D">//creativecommons.org/publicdomain/zero/1.0/</span></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5">\error_reporting</span><span style="color:#24292E">(</span><span style="color:#D73A49">~+!</span><span style="color:#032F62">'We are hiring!'</span><span style="color:#24292E">);</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">$z </span><span style="color:#D73A49">=</span><span style="color:#D73A49"> fn</span><span style="color:#24292E">($f) => (</span><span style="color:#D73A49">fn</span><span style="color:#24292E">($x) => $f(</span><span style="color:#D73A49">fn</span><span style="color:#24292E">(</span><span style="color:#D73A49">...</span><span style="color:#24292E">$xs) => $x($x)(</span><span style="color:#D73A49">...</span><span style="color:#24292E">$xs)))(</span><span style="color:#D73A49">fn</span><span style="color:#24292E">($x) => $f(</span><span style="color:#D73A49">fn</span><span style="color:#24292E">(</span><span style="color:#D73A49">...</span><span style="color:#24292E">$xs) => $x($x)(</span><span style="color:#D73A49">...</span><span style="color:#24292E">$xs)));</span></span> +<span class="line"><span style="color:#24292E">$id </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> \</span><span style="color:#6F42C1">spl_object_id</span><span style="color:#24292E">(</span><span style="color:#D73A49">...</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E">$put </span><span style="color:#D73A49">=</span><span style="color:#D73A49"> fn</span><span style="color:#24292E">($c) => </span><span style="color:#005CC5">\</span><span style="color:#005CC5">printf</span><span style="color:#24292E">(</span><span style="color:#032F62">'%c'</span><span style="color:#24292E">, $c);</span></span> +<span class="line"><span style="color:#24292E">$mm </span><span style="color:#D73A49">=</span><span style="color:#D73A49"> fn</span><span style="color:#24292E">($p, $n) => </span><span style="color:#D73A49">new</span><span style="color:#005CC5"> \ArrayObject</span><span style="color:#24292E">(</span><span style="color:#005CC5">\array_fill</span><span style="color:#24292E">(</span><span style="color:#D73A49">+!!</span><span style="color:#24292E">[], $n, $p));</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">$👉 </span><span style="color:#D73A49">=</span><span style="color:#D73A49"> fn</span><span style="color:#24292E">($m, $p, $b, $e, $mp, $pc) => [</span><span style="color:#D73A49">++</span><span style="color:#24292E">$mp, </span><span style="color:#D73A49">++</span><span style="color:#24292E">$pc];</span></span> +<span class="line"><span style="color:#24292E">$👈 </span><span style="color:#D73A49">=</span><span style="color:#D73A49"> fn</span><span style="color:#24292E">($m, $p, $b, $e, $mp, $pc) => [</span><span style="color:#D73A49">--</span><span style="color:#24292E">$mp, </span><span style="color:#D73A49">++</span><span style="color:#24292E">$pc];</span></span> +<span class="line"><span style="color:#24292E">$👍 </span><span style="color:#D73A49">=</span><span style="color:#D73A49"> fn</span><span style="color:#24292E">($m, $p, $b, $e, $mp, $pc) => [$mp, </span><span style="color:#D73A49">++</span><span style="color:#24292E">$pc, </span><span style="color:#D73A49">++</span><span style="color:#24292E">$m[$mp]];</span></span> +<span class="line"><span style="color:#24292E">$👎 </span><span style="color:#D73A49">=</span><span style="color:#D73A49"> fn</span><span style="color:#24292E">($m, $p, $b, $e, $mp, $pc) => [$mp, </span><span style="color:#D73A49">++</span><span style="color:#24292E">$pc, </span><span style="color:#D73A49">--</span><span style="color:#24292E">$m[$mp]];</span></span> +<span class="line"><span style="color:#24292E">$📝 </span><span style="color:#D73A49">=</span><span style="color:#D73A49"> fn</span><span style="color:#24292E">($m, $p, $b, $e, $mp, $pc) => [$mp, </span><span style="color:#D73A49">++</span><span style="color:#24292E">$pc, $put($m[$mp])];</span></span> +<span class="line"><span style="color:#24292E">$🤡 </span><span style="color:#D73A49">=</span><span style="color:#D73A49"> fn</span><span style="color:#24292E">($m, $p, $b, $e, $mp, $pc) => </span><span style="color:#D73A49">match</span><span style="color:#24292E"> ($m[$mp]) {</span></span> +<span class="line"><span style="color:#D73A49"> +!!</span><span style="color:#24292E">[] </span><span style="color:#D73A49">=></span><span style="color:#24292E"> [$mp, $z(</span><span style="color:#D73A49">fn</span><span style="color:#24292E">($loop) => </span><span style="color:#D73A49">fn</span><span style="color:#24292E">($pc, $n) => </span><span style="color:#D73A49">match</span><span style="color:#24292E"> ($id($p[$pc])) {</span></span> +<span class="line"><span style="color:#24292E"> $b </span><span style="color:#D73A49">=></span><span style="color:#24292E"> $loop(</span><span style="color:#D73A49">++</span><span style="color:#24292E">$pc, </span><span style="color:#D73A49">++</span><span style="color:#24292E">$n),</span></span> +<span class="line"><span style="color:#24292E"> $e </span><span style="color:#D73A49">=></span><span style="color:#24292E"> $n </span><span style="color:#D73A49">===</span><span style="color:#D73A49"> +!!</span><span style="color:#24292E">[] </span><span style="color:#D73A49">?</span><span style="color:#D73A49"> ++</span><span style="color:#24292E">$pc </span><span style="color:#D73A49">:</span><span style="color:#24292E"> $loop(</span><span style="color:#D73A49">++</span><span style="color:#24292E">$pc, </span><span style="color:#D73A49">--</span><span style="color:#24292E">$n),</span></span> +<span class="line"><span style="color:#D73A49"> default</span><span style="color:#D73A49"> =></span><span style="color:#24292E"> $loop(</span><span style="color:#D73A49">++</span><span style="color:#24292E">$pc, $n),</span></span> +<span class="line"><span style="color:#24292E"> })($pc, </span><span style="color:#D73A49">-!</span><span style="color:#24292E">[])],</span></span> +<span class="line"><span style="color:#D73A49"> default</span><span style="color:#D73A49"> =></span><span style="color:#24292E"> [$mp, </span><span style="color:#D73A49">++</span><span style="color:#24292E">$pc],</span></span> +<span class="line"><span style="color:#24292E">};</span></span> +<span class="line"><span style="color:#24292E">$🎪 </span><span style="color:#D73A49">=</span><span style="color:#D73A49"> fn</span><span style="color:#24292E">($m, $p, $b, $e, $mp, $pc) => </span><span style="color:#D73A49">match</span><span style="color:#24292E"> ($m[$mp]) {</span></span> +<span class="line"><span style="color:#D73A49"> +!!</span><span style="color:#24292E">[] </span><span style="color:#D73A49">=></span><span style="color:#24292E"> [$mp, </span><span style="color:#D73A49">++</span><span style="color:#24292E">$pc],</span></span> +<span class="line"><span style="color:#D73A49"> default</span><span style="color:#D73A49"> =></span><span style="color:#24292E"> [$mp, $z(</span><span style="color:#D73A49">fn</span><span style="color:#24292E">($loop) => </span><span style="color:#D73A49">fn</span><span style="color:#24292E">($pc, $n) => </span><span style="color:#D73A49">match</span><span style="color:#24292E"> ($id($p[$pc])) {</span></span> +<span class="line"><span style="color:#24292E"> $e </span><span style="color:#D73A49">=></span><span style="color:#24292E"> $loop(</span><span style="color:#D73A49">--</span><span style="color:#24292E">$pc, </span><span style="color:#D73A49">++</span><span style="color:#24292E">$n),</span></span> +<span class="line"><span style="color:#24292E"> $b </span><span style="color:#D73A49">=></span><span style="color:#24292E"> $n </span><span style="color:#D73A49">===</span><span style="color:#D73A49"> +!!</span><span style="color:#24292E">[] </span><span style="color:#D73A49">?</span><span style="color:#24292E"> $pc</span><span style="color:#D73A49">+!</span><span style="color:#24292E">[] </span><span style="color:#D73A49">:</span><span style="color:#24292E"> $loop(</span><span style="color:#D73A49">--</span><span style="color:#24292E">$pc, </span><span style="color:#D73A49">--</span><span style="color:#24292E">$n),</span></span> +<span class="line"><span style="color:#D73A49"> default</span><span style="color:#D73A49"> =></span><span style="color:#24292E"> $loop(</span><span style="color:#D73A49">--</span><span style="color:#24292E">$pc, $n),</span></span> +<span class="line"><span style="color:#24292E"> })($pc, </span><span style="color:#D73A49">-!</span><span style="color:#24292E">[])],</span></span> +<span class="line"><span style="color:#24292E">};</span></span> +<span class="line"><span style="color:#24292E">$🐘 </span><span style="color:#D73A49">=</span><span style="color:#D73A49"> fn</span><span style="color:#24292E">($p) => $z(</span><span style="color:#D73A49">fn</span><span style="color:#24292E">($loop) => </span><span style="color:#D73A49">fn</span><span style="color:#24292E">($m, $p, $b, $e, $mp, $pc) =></span></span> +<span class="line"><span style="color:#005CC5"> isset</span><span style="color:#24292E">($p[$pc]) </span><span style="color:#D73A49">&&</span><span style="color:#24292E"> $loop($m, $p, $b, $e, </span><span style="color:#D73A49">...</span><span style="color:#24292E">($p[$pc]($m, $p, $b, $e, $mp, $pc)))</span></span> +<span class="line"><span style="color:#24292E">)($mm(</span><span style="color:#D73A49">+!!</span><span style="color:#24292E">[], </span><span style="color:#D73A49">+</span><span style="color:#24292E">(</span><span style="color:#D73A49">!</span><span style="color:#24292E">[]</span><span style="color:#D73A49">.</span><span style="color:#D73A49">!</span><span style="color:#24292E">[])), $p, $id($🤡), $id($🎪), </span><span style="color:#D73A49">+!!</span><span style="color:#24292E">[], </span><span style="color:#D73A49">+!!</span><span style="color:#24292E">[]);</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">$🐘([</span></span> +<span class="line"><span style="color:#24292E"> $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍,</span></span> +<span class="line"><span style="color:#24292E"> $🤡,</span></span> +<span class="line"><span style="color:#24292E"> $👉, $👍, $👍, $👍,</span></span> +<span class="line"><span style="color:#24292E"> $👉, $👍, $👍, $👍, $👍, $👍,</span></span> +<span class="line"><span style="color:#24292E"> $👉, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍,</span></span> +<span class="line"><span style="color:#24292E"> $👉, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍,</span></span> +<span class="line"><span style="color:#24292E"> $👈, $👈, $👈, $👈, $👎,</span></span> +<span class="line"><span style="color:#24292E"> $🎪,</span></span> +<span class="line"><span style="color:#24292E"> $👉, $👍, $👍, $👍, $👍, $👍, $📝,</span></span> +<span class="line"><span style="color:#24292E"> $👎, $👎, $📝,</span></span> +<span class="line"><span style="color:#24292E"> $👉, $👎, $👎, $👎, $📝,</span></span> +<span class="line"><span style="color:#24292E"> $👉, $👎, $👎, $👎, $📝,</span></span> +<span class="line"><span style="color:#24292E"> $👎, $👎, $📝,</span></span> +<span class="line"><span style="color:#24292E"> $👎, $📝,</span></span> +<span class="line"><span style="color:#24292E"> $👈, $📝,</span></span> +<span class="line"><span style="color:#24292E"> $👉, $👉, $👎, $👎, $📝,</span></span> +<span class="line"><span style="color:#24292E"> $👍, $👍, $👍, $👍, $👍, $👍, $👍, $📝,</span></span> +<span class="line"><span style="color:#24292E"> $👈, $👎, $👎, $👎, $👎, $📝,</span></span> +<span class="line"><span style="color:#24292E"> $👈, $📝,</span></span> +<span class="line"><span style="color:#24292E"> $👉, $👍, $👍, $📝,</span></span> +<span class="line"><span style="color:#24292E"> $👉, $👎, $📝,</span></span> +<span class="line"><span style="color:#24292E"> $👈, $📝,</span></span> +<span class="line"><span style="color:#24292E">]);</span></span></code></pre> + </div> <p> この問題は、単に適切なバージョンの PHP で動かせばトークンが得られる。 @@ -181,28 +182,30 @@ $🐘([ なお、brainf*ck プログラムを普通の書き方で書くと、次のようになる。 </p> - <pre class="highlight"><code>+ + + + + + + + + + -[ - > + + + - > + + + + + - > + + + + + + + + + + + + - > + + + + + + + + + + - < < < < - -] -> + + + + + . -- - . -> - - - . -> - - - . -- - . -- . -< . -> > - - . -+ + + + + + + . -< - - - - . -< . -> + + . -> - . -< .</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>+ + + + + + + + + +</span></span> +<span class="line"><span>[</span></span> +<span class="line"><span> > + + +</span></span> +<span class="line"><span> > + + + + +</span></span> +<span class="line"><span> > + + + + + + + + + + + +</span></span> +<span class="line"><span> > + + + + + + + + + +</span></span> +<span class="line"><span> < < < < -</span></span> +<span class="line"><span>]</span></span> +<span class="line"><span>> + + + + + .</span></span> +<span class="line"><span>- - .</span></span> +<span class="line"><span>> - - - .</span></span> +<span class="line"><span>> - - - .</span></span> +<span class="line"><span>- - .</span></span> +<span class="line"><span>- .</span></span> +<span class="line"><span>< .</span></span> +<span class="line"><span>> > - - .</span></span> +<span class="line"><span>+ + + + + + + .</span></span> +<span class="line"><span>< - - - - .</span></span> +<span class="line"><span>< .</span></span> +<span class="line"><span>> + + .</span></span> +<span class="line"><span>> - .</span></span> +<span class="line"><span>< .</span></span></code></pre> + </div> <p> 実行結果はこちら: <a href="https://ideone.com/22VWmb" rel="noreferrer" target="_blank">https://ideone.com/22VWmb</a> @@ -271,7 +274,9 @@ $🐘([ ソースコードのライセンスを示したこの部分だが、 </p> - <pre class="highlight" language="php"><code class="highlight">https:<span class="hljs-comment">//creativecommons.org/publicdomain/zero/1.0/</span></code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6F42C1">https</span><span style="color:#24292E">:</span><span style="color:#6A737D">//creativecommons.org/publicdomain/zero/1.0/</span></span></code></pre> + </div> <p> 完全に合法な PHP のコードである。 <code>https:</code> 部分はラベル、<code>//</code> 以降は行コメントになっている。 @@ -284,11 +289,13 @@ $🐘([ ソースコード中に、ほとんど数値リテラルが書かれていないことにお気づきだろうか。PHP では、型変換を利用することで任意の整数を作り出すことができる。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-title function_ invoke__">assert</span>(<span class="hljs-number">0</span> === +!![]); -<span class="hljs-title function_ invoke__">assert</span>(<span class="hljs-number">1</span> === +![]); -<span class="hljs-title function_ invoke__">assert</span>(<span class="hljs-number">2</span> === ![]+![]); -<span class="hljs-title function_ invoke__">assert</span>(<span class="hljs-number">3</span> === ![]+![]+![]); -<span class="hljs-title function_ invoke__">assert</span>(<span class="hljs-number">10</span> === +(![].+!![]));</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#005CC5">assert</span><span style="color:#24292E">(</span><span style="color:#005CC5">0</span><span style="color:#D73A49"> ===</span><span style="color:#D73A49"> +!!</span><span style="color:#24292E">[]);</span></span> +<span class="line"><span style="color:#005CC5">assert</span><span style="color:#24292E">(</span><span style="color:#005CC5">1</span><span style="color:#D73A49"> ===</span><span style="color:#D73A49"> +!</span><span style="color:#24292E">[]);</span></span> +<span class="line"><span style="color:#005CC5">assert</span><span style="color:#24292E">(</span><span style="color:#005CC5">2</span><span style="color:#D73A49"> ===</span><span style="color:#D73A49"> !</span><span style="color:#24292E">[]</span><span style="color:#D73A49">+!</span><span style="color:#24292E">[]);</span></span> +<span class="line"><span style="color:#005CC5">assert</span><span style="color:#24292E">(</span><span style="color:#005CC5">3</span><span style="color:#D73A49"> ===</span><span style="color:#D73A49"> !</span><span style="color:#24292E">[]</span><span style="color:#D73A49">+!</span><span style="color:#24292E">[]</span><span style="color:#D73A49">+!</span><span style="color:#24292E">[]);</span></span> +<span class="line"><span style="color:#005CC5">assert</span><span style="color:#24292E">(</span><span style="color:#005CC5">10</span><span style="color:#D73A49"> ===</span><span style="color:#D73A49"> +</span><span style="color:#24292E">(</span><span style="color:#D73A49">!</span><span style="color:#24292E">[]</span><span style="color:#D73A49">.</span><span style="color:#D73A49">+!!</span><span style="color:#24292E">[]));</span></span></code></pre> + </div> <p> <code>[]</code> に <code>!</code> を適用すると <code>true</code> が返ってくる。それに <code>+</code> を適用すると、<code>bool</code> から <code>int</code> ヘの型変換が走り、<code>1</code> が生成される。<code>10</code> はさらにトリッキーだ。まず <code>1</code> と <code>0</code> を作り、<code>.</code> で文字列として結合する (<code>'10'</code>)。これに <code>+</code> を適用すると、<code>string</code> から <code>int</code> への型変換が走り、<code>10</code> が生まれる (コード量に頓着しないなら、<code>1</code> を 10 個足し合わせてももちろん 10 が作れる)。 @@ -329,40 +336,42 @@ $🐘([ ソースコードはこちら。実行には PHP 8.0 以上が必要なので注意。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> - -<span class="hljs-comment">/********************************************************* - * This program displays a PHPer token. * - * Guess 'N'. * - * * - * Hints: * - * - N itself has no special meaning, e.g., 42, 8128, * - * it is selected at random. * - * - Each element of $token represents a single letter. * - * - One letter consists of 5x5 cells. * - * - Remember, the output is a complete PHPer token. * - * * - * License: * - * https://creativecommons.org/publicdomain/zero/1.0/ * - *********************************************************/</span> -<span class="hljs-keyword">const</span> <span class="hljs-variable constant_">N</span> = <span class="hljs-number">0</span> <span class="hljs-comment">/* Change it to your answer. */</span>; -<span class="hljs-title function_ invoke__">assert</span>(<span class="hljs-number">0</span> <= N && N <= <span class="hljs-number">0b11111_11111_11111_11111_11111</span>); - -<span class="hljs-variable">$token</span> = [ - <span class="hljs-number">0x14B499C</span>, - <span class="hljs-number">0x0BE34CC</span>, <span class="hljs-number">0x01C9C69</span>, - <span class="hljs-number">0x0ECA069</span>, <span class="hljs-number">0x01C2449</span>, <span class="hljs-number">0x0FDB166</span>, <span class="hljs-number">0x01C9C69</span>, - <span class="hljs-number">0x01C1C66</span>, <span class="hljs-number">0x0FC1C47</span>, <span class="hljs-number">0x01C1C66</span>, - <span class="hljs-number">0x10C5858</span>, <span class="hljs-number">0x1E4E3B8</span>, <span class="hljs-number">0x1A2F2F8</span>, -]; -<span class="hljs-keyword">foreach</span> (<span class="hljs-variable">$token</span> <span class="hljs-keyword">as</span> <span class="hljs-variable">$x</span>) { - <span class="hljs-variable">$x</span> = <span class="hljs-variable">$x</span> ^ N; - - <span class="hljs-variable">$x</span> = <span class="hljs-title function_ invoke__">sprintf</span>(<span class="hljs-string">'%025b'</span>, <span class="hljs-variable">$x</span>); - <span class="hljs-variable">$x</span> = <span class="hljs-title function_ invoke__">str_replace</span>(<span class="hljs-attr">search</span>: [<span class="hljs-string">'0'</span>, <span class="hljs-string">'1'</span>], <span class="hljs-attr">replace</span>: [<span class="hljs-string">' '</span>, <span class="hljs-string">'#'</span>], <span class="hljs-attr">subject</span>: <span class="hljs-variable">$x</span>); - <span class="hljs-variable">$x</span> = <span class="hljs-title function_ invoke__">implode</span>(<span class="hljs-string">"\n"</span>, <span class="hljs-title function_ invoke__">str_split</span>(<span class="hljs-variable">$x</span>, <span class="hljs-attr">length</span>: <span class="hljs-number">5</span>)); - <span class="hljs-keyword">echo</span> <span class="hljs-string">"<span class="hljs-subst">{$x}</span>\n\n"</span>; -}</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6A737D">/*********************************************************</span></span> +<span class="line"><span style="color:#6A737D"> * This program displays a PHPer token. *</span></span> +<span class="line"><span style="color:#6A737D"> * Guess 'N'. *</span></span> +<span class="line"><span style="color:#6A737D"> * *</span></span> +<span class="line"><span style="color:#6A737D"> * Hints: *</span></span> +<span class="line"><span style="color:#6A737D"> * - N itself has no special meaning, e.g., 42, 8128, *</span></span> +<span class="line"><span style="color:#6A737D"> * it is selected at random. *</span></span> +<span class="line"><span style="color:#6A737D"> * - Each element of $token represents a single letter. *</span></span> +<span class="line"><span style="color:#6A737D"> * - One letter consists of 5x5 cells. *</span></span> +<span class="line"><span style="color:#6A737D"> * - Remember, the output is a complete PHPer token. *</span></span> +<span class="line"><span style="color:#6A737D"> * *</span></span> +<span class="line"><span style="color:#6A737D"> * License: *</span></span> +<span class="line"><span style="color:#6A737D"> * https://creativecommons.org/publicdomain/zero/1.0/ *</span></span> +<span class="line"><span style="color:#6A737D"> *********************************************************/</span></span> +<span class="line"><span style="color:#D73A49">const</span><span style="color:#005CC5"> N</span><span style="color:#D73A49"> =</span><span style="color:#005CC5"> 0</span><span style="color:#6A737D"> /* Change it to your answer. */</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#005CC5">assert</span><span style="color:#24292E">(</span><span style="color:#005CC5">0</span><span style="color:#D73A49"> <=</span><span style="color:#005CC5"> N</span><span style="color:#D73A49"> &&</span><span style="color:#005CC5"> N</span><span style="color:#D73A49"> <=</span><span style="color:#005CC5"> 0b11111_11111_11111_11111_11111</span><span style="color:#24292E">);</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">$token </span><span style="color:#D73A49">=</span><span style="color:#24292E"> [</span></span> +<span class="line"><span style="color:#005CC5"> 0x14B499C</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#005CC5"> 0x0BE34CC</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x01C9C69</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#005CC5"> 0x0ECA069</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x01C2449</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x0FDB166</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x01C9C69</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#005CC5"> 0x01C1C66</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x0FC1C47</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x01C1C66</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#005CC5"> 0x10C5858</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x1E4E3B8</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x1A2F2F8</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E">];</span></span> +<span class="line"><span style="color:#D73A49">foreach</span><span style="color:#24292E"> ($token </span><span style="color:#D73A49">as</span><span style="color:#24292E"> $x) {</span></span> +<span class="line"><span style="color:#24292E"> $x </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $x </span><span style="color:#D73A49">^</span><span style="color:#005CC5"> N</span><span style="color:#24292E">;</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E"> $x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> sprintf</span><span style="color:#24292E">(</span><span style="color:#032F62">'%025b'</span><span style="color:#24292E">, $x);</span></span> +<span class="line"><span style="color:#24292E"> $x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> str_replace</span><span style="color:#24292E">(</span><span style="color:#6F42C1">search</span><span style="color:#24292E">: [</span><span style="color:#032F62">'0'</span><span style="color:#24292E">, </span><span style="color:#032F62">'1'</span><span style="color:#24292E">], </span><span style="color:#6F42C1">replace</span><span style="color:#24292E">: [</span><span style="color:#032F62">' '</span><span style="color:#24292E">, </span><span style="color:#032F62">'#'</span><span style="color:#24292E">], </span><span style="color:#6F42C1">subject</span><span style="color:#24292E">: $x);</span></span> +<span class="line"><span style="color:#24292E"> $x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> implode</span><span style="color:#24292E">(</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">, </span><span style="color:#005CC5">str_split</span><span style="color:#24292E">($x, </span><span style="color:#6F42C1">length</span><span style="color:#24292E">: </span><span style="color:#005CC5">5</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#005CC5"> echo</span><span style="color:#032F62"> "{</span><span style="color:#24292E">$x</span><span style="color:#032F62">}</span><span style="color:#005CC5">\n\n</span><span style="color:#032F62">"</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> さて、この問題はさきほどのように単純に実行しただけでは、謎のブロックが表示されるだけでトークンは得られない。トークンを得るためには、ソースコードを読み、定数 <code>N</code> を特定する必要がある。 @@ -378,33 +387,43 @@ $🐘([ まずはソースコードを読んでいく。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$token</span> = [ -<span class="hljs-comment">// 略</span> -];</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$token </span><span style="color:#D73A49">=</span><span style="color:#24292E"> [</span></span> +<span class="line"><span style="color:#6A737D">// 略</span></span> +<span class="line"><span style="color:#24292E">];</span></span></code></pre> + </div> <p> 数値からなる <code>$token</code> があり、各要素をループしている。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$x</span> = <span class="hljs-variable">$x</span> ^ N;</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$x </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $x </span><span style="color:#D73A49">^</span><span style="color:#005CC5"> N</span><span style="color:#24292E">;</span></span></code></pre> + </div> <p> まずは排他的論理和 (xor) を取り、 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$x</span> = <span class="hljs-title function_ invoke__">sprintf</span>(<span class="hljs-string">'%025b'</span>, <span class="hljs-variable">$x</span>);</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> sprintf</span><span style="color:#24292E">(</span><span style="color:#032F62">'%025b'</span><span style="color:#24292E">, $x);</span></span></code></pre> + </div> <p> 二進数に変換して、 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$x</span> = <span class="hljs-title function_ invoke__">str_replace</span>(<span class="hljs-attr">search</span>: [<span class="hljs-string">'0'</span>, <span class="hljs-string">'1'</span>], <span class="hljs-attr">replace</span>: [<span class="hljs-string">' '</span>, <span class="hljs-string">'#'</span>], <span class="hljs-attr">subject</span>: <span class="hljs-variable">$x</span>);</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> str_replace</span><span style="color:#24292E">(</span><span style="color:#6F42C1">search</span><span style="color:#24292E">: [</span><span style="color:#032F62">'0'</span><span style="color:#24292E">, </span><span style="color:#032F62">'1'</span><span style="color:#24292E">], </span><span style="color:#6F42C1">replace</span><span style="color:#24292E">: [</span><span style="color:#032F62">' '</span><span style="color:#24292E">, </span><span style="color:#032F62">'#'</span><span style="color:#24292E">], </span><span style="color:#6F42C1">subject</span><span style="color:#24292E">: $x);</span></span></code></pre> + </div> <p> 0 を空白に、1 を <code>#</code> にし、 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$x</span> = <span class="hljs-title function_ invoke__">implode</span>(<span class="hljs-string">"\n"</span>, <span class="hljs-title function_ invoke__">str_split</span>(<span class="hljs-variable">$x</span>, <span class="hljs-attr">length</span>: <span class="hljs-number">5</span>));</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> implode</span><span style="color:#24292E">(</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">, </span><span style="color:#005CC5">str_split</span><span style="color:#24292E">($x, </span><span style="color:#6F42C1">length</span><span style="color:#24292E">: </span><span style="color:#005CC5">5</span><span style="color:#24292E">));</span></span></code></pre> + </div> <p> 5文字ごとに区切ったあと、改行で結合している。 @@ -450,49 +469,55 @@ $🐘([ <code>N</code> は高々 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-title function_ invoke__">assert</span>(<span class="hljs-number">0</span> <= N && N <= <span class="hljs-number">0b11111_11111_11111_11111_11111</span>);</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#005CC5">assert</span><span style="color:#24292E">(</span><span style="color:#005CC5">0</span><span style="color:#D73A49"> <=</span><span style="color:#005CC5"> N</span><span style="color:#D73A49"> &&</span><span style="color:#005CC5"> N</span><span style="color:#D73A49"> <=</span><span style="color:#005CC5"> 0b11111_11111_11111_11111_11111</span><span style="color:#24292E">);</span></span></code></pre> + </div> <p> なのでブルートフォースしてもよいが、ここではブルートフォースしない方法を紹介する。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> - -<span class="hljs-variable">$x</span> = <span class="hljs-number">0x14B499C</span>; - -<span class="hljs-variable">$x</span> = <span class="hljs-variable">$x</span> ^ N; - -<span class="hljs-variable">$x</span> = <span class="hljs-title function_ invoke__">sprintf</span>(<span class="hljs-string">'%025b'</span>, <span class="hljs-variable">$x</span>); -<span class="hljs-variable">$x</span> = <span class="hljs-title function_ invoke__">str_replace</span>(<span class="hljs-attr">search</span>: [<span class="hljs-string">'0'</span>, <span class="hljs-string">'1'</span>], <span class="hljs-attr">replace</span>: [<span class="hljs-string">' '</span>, <span class="hljs-string">'#'</span>], <span class="hljs-attr">subject</span>: <span class="hljs-variable">$x</span>); -<span class="hljs-variable">$x</span> = <span class="hljs-title function_ invoke__">implode</span>(<span class="hljs-string">"\n"</span>, <span class="hljs-title function_ invoke__">str_split</span>(<span class="hljs-variable">$x</span>, <span class="hljs-attr">length</span>: <span class="hljs-number">5</span>)); - -<span class="hljs-title function_ invoke__">assert</span>(<span class="hljs-variable">$x</span> === -<span class="hljs-string">" # # \n"</span> . -<span class="hljs-string">"#####\n"</span> . -<span class="hljs-string">" # # \n"</span> . -<span class="hljs-string">"#####\n"</span> . -<span class="hljs-string">" # # "</span>);</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">$x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> 0x14B499C</span><span style="color:#24292E">;</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">$x </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $x </span><span style="color:#D73A49">^</span><span style="color:#005CC5"> N</span><span style="color:#24292E">;</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">$x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> sprintf</span><span style="color:#24292E">(</span><span style="color:#032F62">'%025b'</span><span style="color:#24292E">, $x);</span></span> +<span class="line"><span style="color:#24292E">$x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> str_replace</span><span style="color:#24292E">(</span><span style="color:#6F42C1">search</span><span style="color:#24292E">: [</span><span style="color:#032F62">'0'</span><span style="color:#24292E">, </span><span style="color:#032F62">'1'</span><span style="color:#24292E">], </span><span style="color:#6F42C1">replace</span><span style="color:#24292E">: [</span><span style="color:#032F62">' '</span><span style="color:#24292E">, </span><span style="color:#032F62">'#'</span><span style="color:#24292E">], </span><span style="color:#6F42C1">subject</span><span style="color:#24292E">: $x);</span></span> +<span class="line"><span style="color:#24292E">$x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> implode</span><span style="color:#24292E">(</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">, </span><span style="color:#005CC5">str_split</span><span style="color:#24292E">($x, </span><span style="color:#6F42C1">length</span><span style="color:#24292E">: </span><span style="color:#005CC5">5</span><span style="color:#24292E">));</span></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5">assert</span><span style="color:#24292E">($x </span><span style="color:#D73A49">===</span></span> +<span class="line"><span style="color:#032F62">" # # </span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#D73A49"> .</span></span> +<span class="line"><span style="color:#032F62">"#####</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#D73A49"> .</span></span> +<span class="line"><span style="color:#032F62">" # # </span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#D73A49"> .</span></span> +<span class="line"><span style="color:#032F62">"#####</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#D73A49"> .</span></span> +<span class="line"><span style="color:#032F62">" # # "</span><span style="color:#24292E">);</span></span></code></pre> + </div> <p> この一連の変換に対する逆変換を考えると、次のようになる。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> - -<span class="hljs-variable">$x</span> = -<span class="hljs-string">" # # \n"</span> . -<span class="hljs-string">"#####\n"</span> . -<span class="hljs-string">" # # \n"</span> . -<span class="hljs-string">"#####\n"</span> . -<span class="hljs-string">" # # "</span>; - -<span class="hljs-variable">$x</span> = <span class="hljs-title function_ invoke__">implode</span>(<span class="hljs-string">''</span>, <span class="hljs-title function_ invoke__">explode</span>(<span class="hljs-string">"\n"</span>, <span class="hljs-variable">$x</span>)); -<span class="hljs-variable">$x</span> = <span class="hljs-title function_ invoke__">str_replace</span>(<span class="hljs-attr">search</span>: [<span class="hljs-string">' '</span>, <span class="hljs-string">'#'</span>], <span class="hljs-attr">replace</span>: [<span class="hljs-string">'0'</span>, <span class="hljs-string">'1'</span>], <span class="hljs-attr">subject</span>: <span class="hljs-variable">$x</span>); -<span class="hljs-variable">$x</span> = <span class="hljs-title function_ invoke__">bindec</span>(<span class="hljs-variable">$x</span>); - -<span class="hljs-variable">$n</span> = <span class="hljs-variable">$x</span> ^ <span class="hljs-number">0x14B499C</span>; - -<span class="hljs-keyword">echo</span> <span class="hljs-string">"N = <span class="hljs-subst">$n</span>\n"</span>;</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">$x </span><span style="color:#D73A49">=</span></span> +<span class="line"><span style="color:#032F62">" # # </span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#D73A49"> .</span></span> +<span class="line"><span style="color:#032F62">"#####</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#D73A49"> .</span></span> +<span class="line"><span style="color:#032F62">" # # </span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#D73A49"> .</span></span> +<span class="line"><span style="color:#032F62">"#####</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#D73A49"> .</span></span> +<span class="line"><span style="color:#032F62">" # # "</span><span style="color:#24292E">;</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">$x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> implode</span><span style="color:#24292E">(</span><span style="color:#032F62">''</span><span style="color:#24292E">, </span><span style="color:#005CC5">explode</span><span style="color:#24292E">(</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">, $x));</span></span> +<span class="line"><span style="color:#24292E">$x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> str_replace</span><span style="color:#24292E">(</span><span style="color:#6F42C1">search</span><span style="color:#24292E">: [</span><span style="color:#032F62">' '</span><span style="color:#24292E">, </span><span style="color:#032F62">'#'</span><span style="color:#24292E">], </span><span style="color:#6F42C1">replace</span><span style="color:#24292E">: [</span><span style="color:#032F62">'0'</span><span style="color:#24292E">, </span><span style="color:#032F62">'1'</span><span style="color:#24292E">], </span><span style="color:#6F42C1">subject</span><span style="color:#24292E">: $x);</span></span> +<span class="line"><span style="color:#24292E">$x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> bindec</span><span style="color:#24292E">($x);</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">$n </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $x </span><span style="color:#D73A49">^</span><span style="color:#005CC5"> 0x14B499C</span><span style="color:#24292E">;</span></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5">echo</span><span style="color:#032F62"> "N = </span><span style="color:#24292E">$n</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">;</span></span></code></pre> + </div> <p> これを実行すると、<code>N</code> が得られる。 @@ -506,41 +531,45 @@ $🐘([ ソースコードはこちら。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> - -<span class="hljs-comment">// License: https://creativecommons.org/publicdomain/zero/1.0/</span> -<span class="hljs-comment">// This is a quine-like program to generate a PHPer token.</span> -<span class="hljs-comment">// Execute it like this: php toquine.php | php | php | php | ...</span> - -<span class="hljs-variable">$s</span> = <span class="hljs-string"><<<'Q' -<?cuc -// Yvprafr: uggcf://perngvirpbzzbaf.bet/choyvpqbznva/mreb/1.0/ -// Guvf vf n dhvar-yvxr cebtenz gb trarengr n CUCre gbxra. -// Rkrphgr vg yvxr guvf: cuc gbdhvar.cuc | cuc | cuc | cuc | ... -%f$f = %f; -$f = fge_ebg13($f); $kf = [ -%f, -]; -$g = ahyy.snyfr; sbe ($v = 0; $v <= vagqvi(__YVAR__-035,6); ++$v) vs (!vffrg($kf[$v])) oernx; ryfr -$g .= vzcybqr("\a", fge_fcyvg(fge_ercynpr(['0','1'], [' ','##'], fcevags(pue(37) . '025o', $kf[$v])), 012)) . "\a\a"; -$jf = neenl_znc(sa($j) => vzcybqr(', ', $j), neenl_puhax(neenl_znc(sa($k) => fcevags('0k' . pue(37) . '07K', $k), $kf), 10)); -cevags($f, $g, fge_ebg13("<<<'Q</span><span class="hljs-string">'\a{$f}\aQ"), vzcybqr(",\a", $jf)); -Q; -$s = str_rot13($s); $xs = [ -0x0AFABEA, 0x1F294A7, 0x1F2109F, 0x1F294A7, 0x0002800, 0x1F2109F, 0x0117041, 0x1F294A7, 0x1FAD6B5, 0x1F295B7, -0x010FC21, 0x1FAD6B5, 0x1151151, 0x010FC21, 0x1F294A7, 0x1F295B7, 0x1FAD6B5, 0x1F294A7, 0x1F295B7, 0x1F8C63F, -0x1F8C631, 0x1FAD6B5, 0x17AD6BD, 0x17AD6BD, 0x1F8C63F, 0x1F295B7, -]; -$t = null.false; for ($i = 0; $i <= intdiv(__LINE__-035,6); ++$i) if (!isset($xs[$i])) break; else -$t .= implode("\n", str_split(str_replace(['</span><span class="hljs-number">0</span><span class="hljs-string">','</span><span class="hljs-number">1</span><span class="hljs-string">'], ['</span> <span class="hljs-string">','</span><span class="hljs-comment">##'], sprintf(chr(37) . '025b', $xs[$i])), 012)) . "\n\n";</span> -<span class="hljs-variable">$ws</span> = <span class="hljs-title function_ invoke__">array_map</span>(fn(<span class="hljs-variable">$w</span>) => <span class="hljs-title function_ invoke__">implode</span>(<span class="hljs-string">', '</span>, <span class="hljs-variable">$w</span>), <span class="hljs-title function_ invoke__">array_chunk</span>(<span class="hljs-title function_ invoke__">array_map</span>(fn(<span class="hljs-variable">$x</span>) => <span class="hljs-title function_ invoke__">sprintf</span>(<span class="hljs-string">'0x'</span> . <span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-number">37</span>) . <span class="hljs-string">'07X'</span>, <span class="hljs-variable">$x</span>), <span class="hljs-variable">$xs</span>), <span class="hljs-number">10</span>)); -<span class="hljs-title function_ invoke__">printf</span>(<span class="hljs-variable">$s</span>, <span class="hljs-variable">$t</span>, <span class="hljs-title function_ invoke__">str_rot13</span>(<span class="hljs-string">"<<<'D'\n<span class="hljs-subst">{$s}</span>\nD"</span>), <span class="hljs-title function_ invoke__">implode</span>(<span class="hljs-string">",\n"</span>, <span class="hljs-variable">$ws</span>));</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6A737D">// License: https://creativecommons.org/publicdomain/zero/1.0/</span></span> +<span class="line"><span style="color:#6A737D">// This is a quine-like program to generate a PHPer token.</span></span> +<span class="line"><span style="color:#6A737D">// Execute it like this: php toquine.php | php | php | php | ...</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">$s </span><span style="color:#D73A49">=</span><span style="color:#032F62"> <<<'</span><span style="color:#D73A49">Q</span><span style="color:#032F62">'</span></span> +<span class="line"><span style="color:#032F62"><?cuc</span></span> +<span class="line"><span style="color:#032F62">// Yvprafr: uggcf://perngvirpbzzbaf.bet/choyvpqbznva/mreb/1.0/</span></span> +<span class="line"><span style="color:#032F62">// Guvf vf n dhvar-yvxr cebtenz gb trarengr n CUCre gbxra.</span></span> +<span class="line"><span style="color:#032F62">// Rkrphgr vg yvxr guvf: cuc gbdhvar.cuc | cuc | cuc | cuc | ...</span></span> +<span class="line"><span style="color:#032F62">%f$f = %f;</span></span> +<span class="line"><span style="color:#032F62">$f = fge_ebg13($f); $kf = [</span></span> +<span class="line"><span style="color:#032F62">%f,</span></span> +<span class="line"><span style="color:#032F62">];</span></span> +<span class="line"><span style="color:#032F62">$g = ahyy.snyfr; sbe ($v = 0; $v <= vagqvi(__YVAR__-035,6); ++$v) vs (!vffrg($kf[$v])) oernx; ryfr</span></span> +<span class="line"><span style="color:#032F62">$g .= vzcybqr("\a", fge_fcyvg(fge_ercynpr(['0','1'], [' ','##'], fcevags(pue(37) . '025o', $kf[$v])), 012)) . "\a\a";</span></span> +<span class="line"><span style="color:#032F62">$jf = neenl_znc(sa($j) => vzcybqr(', ', $j), neenl_puhax(neenl_znc(sa($k) => fcevags('0k' . pue(37) . '07K', $k), $kf), 10));</span></span> +<span class="line"><span style="color:#032F62">cevags($f, $g, fge_ebg13("<<<'Q'\a{$f}\aQ"), vzcybqr(",\a", $jf));</span></span> +<span class="line"><span style="color:#D73A49">Q</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$s </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> str_rot13</span><span style="color:#24292E">($s); $xs </span><span style="color:#D73A49">=</span><span style="color:#24292E"> [</span></span> +<span class="line"><span style="color:#005CC5">0x0AFABEA</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x1F294A7</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x1F2109F</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x1F294A7</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x0002800</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x1F2109F</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x0117041</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x1F294A7</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x1FAD6B5</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x1F295B7</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#005CC5">0x010FC21</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x1FAD6B5</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x1151151</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x010FC21</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x1F294A7</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x1F295B7</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x1FAD6B5</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x1F294A7</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x1F295B7</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x1F8C63F</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#005CC5">0x1F8C631</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x1FAD6B5</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x17AD6BD</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x17AD6BD</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x1F8C63F</span><span style="color:#24292E">, </span><span style="color:#005CC5">0x1F295B7</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E">];</span></span> +<span class="line"><span style="color:#24292E">$t </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> null</span><span style="color:#D73A49">.</span><span style="color:#005CC5">false</span><span style="color:#24292E">; </span><span style="color:#D73A49">for</span><span style="color:#24292E"> ($i </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">; $i </span><span style="color:#D73A49"><=</span><span style="color:#6F42C1"> intdiv</span><span style="color:#24292E">(</span><span style="color:#005CC5">__LINE__</span><span style="color:#D73A49">-</span><span style="color:#005CC5">035</span><span style="color:#24292E">,</span><span style="color:#005CC5">6</span><span style="color:#24292E">); </span><span style="color:#D73A49">++</span><span style="color:#24292E">$i) </span><span style="color:#D73A49">if</span><span style="color:#24292E"> (</span><span style="color:#D73A49">!</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($xs[$i])) </span><span style="color:#D73A49">break</span><span style="color:#24292E">; </span><span style="color:#D73A49">else</span></span> +<span class="line"><span style="color:#24292E">$t </span><span style="color:#D73A49">.=</span><span style="color:#005CC5"> implode</span><span style="color:#24292E">(</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">, </span><span style="color:#005CC5">str_split</span><span style="color:#24292E">(</span><span style="color:#005CC5">str_replace</span><span style="color:#24292E">([</span><span style="color:#032F62">'0'</span><span style="color:#24292E">,</span><span style="color:#032F62">'1'</span><span style="color:#24292E">], [</span><span style="color:#032F62">' '</span><span style="color:#24292E">,</span><span style="color:#032F62">'##'</span><span style="color:#24292E">], </span><span style="color:#005CC5">sprintf</span><span style="color:#24292E">(</span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">37</span><span style="color:#24292E">) </span><span style="color:#D73A49">.</span><span style="color:#032F62"> '025b'</span><span style="color:#24292E">, $xs[$i])), </span><span style="color:#005CC5">012</span><span style="color:#24292E">)) </span><span style="color:#D73A49">.</span><span style="color:#032F62"> "</span><span style="color:#005CC5">\n\n</span><span style="color:#032F62">"</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$ws </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> array_map</span><span style="color:#24292E">(</span><span style="color:#D73A49">fn</span><span style="color:#24292E">($w) => </span><span style="color:#005CC5">implode</span><span style="color:#24292E">(</span><span style="color:#032F62">', '</span><span style="color:#24292E">, $w), </span><span style="color:#005CC5">array_chunk</span><span style="color:#24292E">(</span><span style="color:#005CC5">array_map</span><span style="color:#24292E">(</span><span style="color:#D73A49">fn</span><span style="color:#24292E">($x) => </span><span style="color:#005CC5">sprintf</span><span style="color:#24292E">(</span><span style="color:#032F62">'0x'</span><span style="color:#D73A49"> .</span><span style="color:#005CC5"> chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">37</span><span style="color:#24292E">) </span><span style="color:#D73A49">.</span><span style="color:#032F62"> '07X'</span><span style="color:#24292E">, $x), $xs), </span><span style="color:#005CC5">10</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#005CC5">printf</span><span style="color:#24292E">($s, $t, </span><span style="color:#005CC5">str_rot13</span><span style="color:#24292E">(</span><span style="color:#032F62">"<<<'D'</span><span style="color:#005CC5">\n</span><span style="color:#032F62">{</span><span style="color:#24292E">$s</span><span style="color:#032F62">}</span><span style="color:#005CC5">\n</span><span style="color:#032F62">D"</span><span style="color:#24292E">), </span><span style="color:#005CC5">implode</span><span style="color:#24292E">(</span><span style="color:#032F62">",</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">, $ws));</span></span></code></pre> + </div> <p> コメントにもあるとおり、次のようにして実行すれば答えがでてくる。 </p> - <pre class="highlight" language="shell-session"><code>$ php toquine.php | php | php | php | ...</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ php toquine.php | php | php | php | ...</span></span></code></pre> + </div> <p> 実際にはもう少しパイプで繋げなければならない。 diff --git a/vhosts/blog/public/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal/index.html b/vhosts/blog/public/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal/index.html index d3d21364..ff722cda 100644 --- a/vhosts/blog/public/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal/index.html +++ b/vhosts/blog/public/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal/index.html @@ -13,8 +13,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>term-banner: ターミナルにバナーを表示するツールを書いた|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -61,7 +60,9 @@ こんなものを作った。 </p> - <pre class="highlight"><code>$ term-banner 'Hello, World!' 'こんにちは、' '世界!'</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ term-banner 'Hello, World!' 'こんにちは、' '世界!'</span></span></code></pre> + </div> <img alt="term-banner が動作している様子のスクリーンショット" src="/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal/screenshot.png"> </img> diff --git a/vhosts/blog/public/posts/2022-05-01/phperkaigi-2022/index.html b/vhosts/blog/public/posts/2022-05-01/phperkaigi-2022/index.html index 37c10d45..9ba40f11 100644 --- a/vhosts/blog/public/posts/2022-05-01/phperkaigi-2022/index.html +++ b/vhosts/blog/public/posts/2022-05-01/phperkaigi-2022/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>PHPerKaigi 2022|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> diff --git a/vhosts/blog/public/posts/2022-08-27/php-conference-okinawa-code-golf/index.html b/vhosts/blog/public/posts/2022-08-27/php-conference-okinawa-code-golf/index.html index 1f7ad6ba..ed87f02e 100644 --- a/vhosts/blog/public/posts/2022-08-27/php-conference-okinawa-code-golf/index.html +++ b/vhosts/blog/public/posts/2022-08-27/php-conference-okinawa-code-golf/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>PHP カンファレンス沖縄で出題されたコードゴルフの問題を解いてみた|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -121,7 +120,9 @@ 書いたものがこちら: </p> - <pre class="highlight" language="php"><code class="highlight">[<span class="hljs-meta"><?php</span> <span class="hljs-variable">$n</span>=<span class="hljs-variable">$argv</span>[<span class="hljs-number">1</span>];<span class="hljs-keyword">foreach</span>([<span class="hljs-number">1e4</span>,<span class="hljs-number">5e3</span>,<span class="hljs-number">2e3</span>,<span class="hljs-number">1e3</span>,<span class="hljs-number">500</span>,<span class="hljs-number">100</span>,<span class="hljs-number">50</span>,<span class="hljs-number">10</span>,<span class="hljs-number">5</span>,<span class="hljs-number">1</span>]<span class="hljs-keyword">as</span><span class="hljs-variable">$x</span>)<span class="hljs-keyword">for</span>(;<span class="hljs-variable">$n</span>>=<span class="hljs-variable">$x</span>;<span class="hljs-variable">$n</span>-=<span class="hljs-variable">$x</span>)<span class="hljs-variable">$r</span>[]=<span class="hljs-variable">$x</span>;<span class="hljs-keyword">echo</span> <span class="hljs-title function_ invoke__">implode</span>(<span class="hljs-string">', '</span>,<span class="hljs-variable">$r</span>??[]);<span class="hljs-meta">?></span>]</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">[</span><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#24292E"> $n</span><span style="color:#D73A49">=</span><span style="color:#24292E">$argv[</span><span style="color:#005CC5">1</span><span style="color:#24292E">];</span><span style="color:#D73A49">foreach</span><span style="color:#24292E">([</span><span style="color:#005CC5">1e4</span><span style="color:#24292E">,</span><span style="color:#005CC5">5e3</span><span style="color:#24292E">,</span><span style="color:#005CC5">2e3</span><span style="color:#24292E">,</span><span style="color:#005CC5">1e3</span><span style="color:#24292E">,</span><span style="color:#005CC5">500</span><span style="color:#24292E">,</span><span style="color:#005CC5">100</span><span style="color:#24292E">,</span><span style="color:#005CC5">50</span><span style="color:#24292E">,</span><span style="color:#005CC5">10</span><span style="color:#24292E">,</span><span style="color:#005CC5">5</span><span style="color:#24292E">,</span><span style="color:#005CC5">1</span><span style="color:#24292E">]</span><span style="color:#D73A49">as</span><span style="color:#24292E">$x)</span><span style="color:#D73A49">for</span><span style="color:#24292E">(;$n</span><span style="color:#D73A49">>=</span><span style="color:#24292E">$x;$n</span><span style="color:#D73A49">-=</span><span style="color:#24292E">$x)$r[]</span><span style="color:#D73A49">=</span><span style="color:#24292E">$x;</span><span style="color:#005CC5">echo</span><span style="color:#005CC5"> implode</span><span style="color:#24292E">(</span><span style="color:#032F62">', '</span><span style="color:#24292E">,$r</span><span style="color:#D73A49">??</span><span style="color:#24292E">[]);</span><span style="color:#D73A49">?></span><span style="color:#24292E">]</span></span></code></pre> + </div> <p> しめて 123 バイトとなった (末尾改行を含めずにカウント)。 @@ -131,15 +132,17 @@ こちらは改行とスペースを追加したバージョン: </p> - <pre class="highlight" language="php"><code class="highlight">[<span class="hljs-meta"><?php</span> - -<span class="hljs-variable">$n</span> = <span class="hljs-variable">$argv</span>[<span class="hljs-number">1</span>]; -<span class="hljs-keyword">foreach</span> ([<span class="hljs-number">1e4</span>, <span class="hljs-number">5e3</span>, <span class="hljs-number">2e3</span>, <span class="hljs-number">1e3</span>, <span class="hljs-number">500</span>, <span class="hljs-number">100</span>, <span class="hljs-number">50</span>, <span class="hljs-number">10</span>, <span class="hljs-number">5</span>, <span class="hljs-number">1</span>] <span class="hljs-keyword">as</span> <span class="hljs-variable">$x</span>) - <span class="hljs-keyword">for</span> (; <span class="hljs-variable">$n</span> >= <span class="hljs-variable">$x</span>; <span class="hljs-variable">$n</span> -= <span class="hljs-variable">$x</span>) - <span class="hljs-variable">$r</span>[] = <span class="hljs-variable">$x</span>; -<span class="hljs-keyword">echo</span> <span class="hljs-title function_ invoke__">implode</span>(<span class="hljs-string">', '</span>, <span class="hljs-variable">$r</span> ?? []); - -<span class="hljs-meta">?></span>]</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">[</span><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">$n </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $argv[</span><span style="color:#005CC5">1</span><span style="color:#24292E">];</span></span> +<span class="line"><span style="color:#D73A49">foreach</span><span style="color:#24292E"> ([</span><span style="color:#005CC5">1e4</span><span style="color:#24292E">, </span><span style="color:#005CC5">5e3</span><span style="color:#24292E">, </span><span style="color:#005CC5">2e3</span><span style="color:#24292E">, </span><span style="color:#005CC5">1e3</span><span style="color:#24292E">, </span><span style="color:#005CC5">500</span><span style="color:#24292E">, </span><span style="color:#005CC5">100</span><span style="color:#24292E">, </span><span style="color:#005CC5">50</span><span style="color:#24292E">, </span><span style="color:#005CC5">10</span><span style="color:#24292E">, </span><span style="color:#005CC5">5</span><span style="color:#24292E">, </span><span style="color:#005CC5">1</span><span style="color:#24292E">] </span><span style="color:#D73A49">as</span><span style="color:#24292E"> $x)</span></span> +<span class="line"><span style="color:#D73A49"> for</span><span style="color:#24292E"> (; $n </span><span style="color:#D73A49">>=</span><span style="color:#24292E"> $x; $n </span><span style="color:#D73A49">-=</span><span style="color:#24292E"> $x)</span></span> +<span class="line"><span style="color:#24292E"> $r[] </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $x;</span></span> +<span class="line"><span style="color:#005CC5">echo</span><span style="color:#005CC5"> implode</span><span style="color:#24292E">(</span><span style="color:#032F62">', '</span><span style="color:#24292E">, $r </span><span style="color:#D73A49">??</span><span style="color:#24292E"> []);</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">?></span><span style="color:#24292E">]</span></span></code></pre> + </div> </section> <section id="section--techniques"> diff --git a/vhosts/blog/public/posts/2022-08-31/support-for-communty-is-employee-benefits/index.html b/vhosts/blog/public/posts/2022-08-31/support-for-communty-is-employee-benefits/index.html index fb44e927..9409eb8d 100644 --- a/vhosts/blog/public/posts/2022-08-31/support-for-communty-is-employee-benefits/index.html +++ b/vhosts/blog/public/posts/2022-08-31/support-for-communty-is-employee-benefits/index.html @@ -13,8 +13,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>弊社の PHP Foundation への寄付に寄せて|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> diff --git a/vhosts/blog/public/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/index.html b/vhosts/blog/public/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/index.html index ab8e1136..44e3dc2e 100644 --- a/vhosts/blog/public/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/index.html +++ b/vhosts/blog/public/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>【PHP】 fizzbuzz を書く。1行あたり2文字で。|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -125,80 +124,82 @@ 特に、C言語でこのような試みをおこなったことがあるかたならそう思うだろう。事実、Cでのこの制約はほとんど無意味に等しい。 </p> - <pre class="highlight" language="c"><code class="highlight">#\ -i\ -n\ -c\ -l\ -u\ -d\ -e\ -<\ -s\ -t\ -d\ -i\ -o\ -.\ -h\ ->\ -<span class="hljs-comment">/* -*/</span> -i\ -n\ -t\ -<span class="hljs-comment">/* -*/</span> -m\ -a\ -i\ -n( -){ -f\ -o\ -r( -i\ -n\ -t\ -<span class="hljs-comment">/* -*/</span> -i= -<span class="hljs-number">1</span>; -i< -<span class="hljs-number">1</span>\ -<span class="hljs-number">0</span>\ -<span class="hljs-number">0</span>; -i\ -+\ -+) -<span class="hljs-keyword">if</span> -(i -%\ -<span class="hljs-number">15</span> -== -<span class="hljs-number">0</span>) -p\ -r\ -i\ -n\ -t\ -f( -<span class="hljs-string">"\ -F\ -i\ -z\ -z\ -B\ -u\ -z\ -z\ -%\ -c\ -"</span>, -<span class="hljs-number">10</span> -); - -<span class="hljs-comment">/* あとは同じように普通のプログラムを変形するだけなので省略 */</span></code></pre> + <div class="codeblock" language="c"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">#</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">i</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">n</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">c</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">l</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">u</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">d</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">e</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#D73A49"><</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">s</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">t</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">d</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">i</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">o</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">.</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">h</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#D73A49">></span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#6A737D">/*</span></span> +<span class="line"><span style="color:#6A737D">*/</span></span> +<span class="line"><span style="color:#24292E">i</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">n</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">t</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#6A737D">/*</span></span> +<span class="line"><span style="color:#6A737D">*/</span></span> +<span class="line"><span style="color:#24292E">m</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">a</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">i</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#6F42C1">n</span><span style="color:#24292E">(</span></span> +<span class="line"><span style="color:#24292E">){</span></span> +<span class="line"><span style="color:#24292E">f</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">o</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#6F42C1">r</span><span style="color:#24292E">(</span></span> +<span class="line"><span style="color:#24292E">i</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">n</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">t</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#6A737D">/*</span></span> +<span class="line"><span style="color:#6A737D">*/</span></span> +<span class="line"><span style="color:#24292E">i</span><span style="color:#D73A49">=</span></span> +<span class="line"><span style="color:#005CC5">1</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">i</span><span style="color:#D73A49"><</span></span> +<span class="line"><span style="color:#005CC5">1\</span></span> +<span class="line"><span style="color:#005CC5">0\</span></span> +<span class="line"><span style="color:#005CC5">0</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">i</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#D73A49">+</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#D73A49">+</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#D73A49">if</span></span> +<span class="line"><span style="color:#24292E">(i</span></span> +<span class="line"><span style="color:#D73A49">%</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#005CC5">15</span></span> +<span class="line"><span style="color:#D73A49">==</span></span> +<span class="line"><span style="color:#005CC5">0</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#24292E">p</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">r</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">i</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">n</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#24292E">t</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#6F42C1">f</span><span style="color:#24292E">(</span></span> +<span class="line"><span style="color:#032F62">"</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#032F62">F</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#032F62">i</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#032F62">z</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#032F62">z</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#032F62">B</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#032F62">u</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#032F62">z</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#032F62">z</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#B31D28;font-style:italic">%</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#032F62">c</span><span style="color:#005CC5">\</span></span> +<span class="line"><span style="color:#032F62">"</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#005CC5">10</span></span> +<span class="line"><span style="color:#24292E">);</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6A737D">/* あとは同じように普通のプログラムを変形するだけなので省略 */</span></span></code></pre> + </div> <p> バックスラッシュを使った行継続がトークンを区切らない、というのがポイントだ。 @@ -250,10 +251,12 @@ c\ また、2文字だと文字列がまともに書けないのも辛い。<code>''</code> だけで2文字使うので、「1文字の文字列リテラル」というものを書くことができない。PHP では文字列リテラル中に生の改行が書けるので </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$a</span> -=<span class="hljs-string">' -a'</span> -;;</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$a</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#032F62">'</span></span> +<span class="line"><span style="color:#032F62">a'</span></span> +<span class="line"><span style="color:#24292E">;;</span></span></code></pre> + </div> <p> とすると <code>$a</code> は <code>"\na"</code> になるのだが、余計な改行が入ってしまう。 @@ -272,11 +275,13 @@ a'</span> まずは普通に書くとしよう。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> - -<span class="hljs-keyword">for</span> (<span class="hljs-variable">$i</span> = <span class="hljs-number">1</span>; <span class="hljs-variable">$i</span> < <span class="hljs-number">100</span>; <span class="hljs-variable">$i</span>++) { - <span class="hljs-keyword">echo</span> ((<span class="hljs-variable">$i</span> % <span class="hljs-number">3</span> ? <span class="hljs-string">''</span> : <span class="hljs-string">'Fizz'</span>) . (<span class="hljs-variable">$i</span> % <span class="hljs-number">5</span> ? <span class="hljs-string">''</span> : <span class="hljs-string">'Buzz'</span>) ?: <span class="hljs-variable">$i</span>) . <span class="hljs-string">"\n"</span>; -}</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">for</span><span style="color:#24292E"> ($i </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> 1</span><span style="color:#24292E">; $i </span><span style="color:#D73A49"><</span><span style="color:#005CC5"> 100</span><span style="color:#24292E">; $i</span><span style="color:#D73A49">++</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#005CC5"> echo</span><span style="color:#24292E"> (($i </span><span style="color:#D73A49">%</span><span style="color:#005CC5"> 3</span><span style="color:#D73A49"> ?</span><span style="color:#032F62"> ''</span><span style="color:#D73A49"> :</span><span style="color:#032F62"> 'Fizz'</span><span style="color:#24292E">) </span><span style="color:#D73A49">.</span><span style="color:#24292E"> ($i </span><span style="color:#D73A49">%</span><span style="color:#005CC5"> 5</span><span style="color:#D73A49"> ?</span><span style="color:#032F62"> ''</span><span style="color:#D73A49"> :</span><span style="color:#032F62"> 'Buzz'</span><span style="color:#24292E">) </span><span style="color:#D73A49">?:</span><span style="color:#24292E"> $i) </span><span style="color:#D73A49">.</span><span style="color:#032F62"> "</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> 素直に書いた fizzbuzz とは言い難いが、このくらいは普通だということにしておかないと、この先がやっていられないので許してほしい。 @@ -289,14 +294,16 @@ a'</span> <code>for</code> は、3文字もある長いキーワードである。こんなものは使えない。<code>array_</code> 系の関数を使って、適当に置き換えるとしよう。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> - -<span class="hljs-variable">$s</span> = <span class="hljs-title function_ invoke__">range</span>(<span class="hljs-number">1</span>, <span class="hljs-number">100</span>); -<span class="hljs-title function_ invoke__">array_walk</span>( -<span class="hljs-variable">$s</span>, -fn(<span class="hljs-variable">$i</span>) => -<span class="hljs-title function_ invoke__">printf</span>(((<span class="hljs-variable">$i</span> % <span class="hljs-number">3</span> ? <span class="hljs-string">''</span> : <span class="hljs-string">'Fizz'</span>) . (<span class="hljs-variable">$i</span> % <span class="hljs-number">5</span> ? <span class="hljs-string">''</span> : <span class="hljs-string">'Buzz'</span>) ?: <span class="hljs-variable">$i</span>) . <span class="hljs-string">"\n"</span>), -);</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">$s </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> range</span><span style="color:#24292E">(</span><span style="color:#005CC5">1</span><span style="color:#24292E">, </span><span style="color:#005CC5">100</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#005CC5">array_walk</span><span style="color:#24292E">(</span></span> +<span class="line"><span style="color:#24292E">$s,</span></span> +<span class="line"><span style="color:#D73A49">fn</span><span style="color:#24292E">($i) =></span></span> +<span class="line"><span style="color:#005CC5">printf</span><span style="color:#24292E">((($i </span><span style="color:#D73A49">%</span><span style="color:#005CC5"> 3</span><span style="color:#D73A49"> ?</span><span style="color:#032F62"> ''</span><span style="color:#D73A49"> :</span><span style="color:#032F62"> 'Fizz'</span><span style="color:#24292E">) </span><span style="color:#D73A49">.</span><span style="color:#24292E"> ($i </span><span style="color:#D73A49">%</span><span style="color:#005CC5"> 5</span><span style="color:#D73A49"> ?</span><span style="color:#032F62"> ''</span><span style="color:#D73A49"> :</span><span style="color:#032F62"> 'Buzz'</span><span style="color:#24292E">) </span><span style="color:#D73A49">?:</span><span style="color:#24292E"> $i) </span><span style="color:#D73A49">.</span><span style="color:#032F62"> "</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">),</span></span> +<span class="line"><span style="color:#24292E">);</span></span></code></pre> + </div> <p> <code>array_walk</code> や <code>range</code>、<code>printf</code> といった <code>for</code> よりも長いトークンが現れてしまったが、これは次節で直すことにする。なお、<code>echo</code> は文 (statement) であり式 (expression) ではないので、式である <code>printf</code> に置き換えた。 @@ -309,18 +316,20 @@ fn(<span class="hljs-variable">$i</span>) => <code>range</code>、<code>array_walk</code>、<code>printf</code> は長すぎるのでどうにかせねばならない。ここで、PHP の可変関数を使う。可変関数とは、関数名が文字列として入った変数を経由して、関数を呼び出す機能である。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> - -<span class="hljs-variable">$r</span> = <span class="hljs-string">'range'</span>; -<span class="hljs-variable">$w</span> = <span class="hljs-string">'array_walk'</span>; -<span class="hljs-variable">$p</span> = <span class="hljs-string">'printf'</span>; - -<span class="hljs-variable">$s</span> = <span class="hljs-variable">$r</span>(<span class="hljs-number">1</span>, <span class="hljs-number">100</span>); -<span class="hljs-variable">$w</span>( -<span class="hljs-variable">$s</span>, -<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$i</span></span>) =></span> -<span class="hljs-variable">$p</span>(((<span class="hljs-variable">$i</span> % <span class="hljs-number">3</span> ? <span class="hljs-string">''</span> : <span class="hljs-string">'Fizz'</span>) . (<span class="hljs-variable">$i</span> % <span class="hljs-number">5</span> ? <span class="hljs-string">''</span> : <span class="hljs-string">'Buzz'</span>) ?: <span class="hljs-variable">$i</span>) . <span class="hljs-string">"\n"</span>), -);</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">$r </span><span style="color:#D73A49">=</span><span style="color:#032F62"> 'range'</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$w </span><span style="color:#D73A49">=</span><span style="color:#032F62"> 'array_walk'</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$p </span><span style="color:#D73A49">=</span><span style="color:#032F62"> 'printf'</span><span style="color:#24292E">;</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">$s </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $r(</span><span style="color:#005CC5">1</span><span style="color:#24292E">, </span><span style="color:#005CC5">100</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E">$w(</span></span> +<span class="line"><span style="color:#24292E">$s,</span></span> +<span class="line"><span style="color:#D73A49">fn</span><span style="color:#24292E">($i) =></span></span> +<span class="line"><span style="color:#24292E">$p((($i </span><span style="color:#D73A49">%</span><span style="color:#005CC5"> 3</span><span style="color:#D73A49"> ?</span><span style="color:#032F62"> ''</span><span style="color:#D73A49"> :</span><span style="color:#032F62"> 'Fizz'</span><span style="color:#24292E">) </span><span style="color:#D73A49">.</span><span style="color:#24292E"> ($i </span><span style="color:#D73A49">%</span><span style="color:#005CC5"> 5</span><span style="color:#D73A49"> ?</span><span style="color:#032F62"> ''</span><span style="color:#D73A49"> :</span><span style="color:#032F62"> 'Buzz'</span><span style="color:#24292E">) </span><span style="color:#D73A49">?:</span><span style="color:#24292E"> $i) </span><span style="color:#D73A49">.</span><span style="color:#032F62"> "</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">),</span></span> +<span class="line"><span style="color:#24292E">);</span></span></code></pre> + </div> <p> これで関数を呼び出している所は短くなった。では、<code>$r</code> や <code>$w</code> や <code>$p</code>、また <code>'Fizz'</code> や <code>'Buzz'</code> はどうやって 1 行 2 文字に収めるのか。次のテクニックへ移ろう。 @@ -345,26 +354,30 @@ fn(<span class="hljs-variable">$i</span>) => というルールがない場合、「未定義の定数が評価された場合、その定数の名前が値になる」という PHP 7.x までの仕様が利用できる。例えば、 <code>Fizz</code> という文字列が欲しければ、次のようにする。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$f</span> -=F -.i -.z -.z -;;</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$f</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#005CC5">F</span></span> +<span class="line"><span style="color:#D73A49">.</span><span style="color:#005CC5">i</span></span> +<span class="line"><span style="color:#D73A49">.</span><span style="color:#005CC5">z</span></span> +<span class="line"><span style="color:#D73A49">.</span><span style="color:#005CC5">z</span></span> +<span class="line"><span style="color:#24292E">;;</span></span></code></pre> + </div> <p> こうして簡単に文字列を作れる。なお、この仕様は 7.x 時点でも警告を受けるので、<code>@</code> 演算子を使って抑制してやるとよい。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$f</span> -=@ -F. -@i -.<span class="hljs-comment">#</span> -@z -.<span class="hljs-comment">#</span> -@z -;;</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$f</span></span> +<span class="line"><span style="color:#D73A49">=@</span></span> +<span class="line"><span style="color:#005CC5">F</span><span style="color:#D73A49">.</span></span> +<span class="line"><span style="color:#D73A49">@</span><span style="color:#005CC5">i</span></span> +<span class="line"><span style="color:#D73A49">.</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#D73A49">@</span><span style="color:#005CC5">z</span></span> +<span class="line"><span style="color:#D73A49">.</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#D73A49">@</span><span style="color:#005CC5">z</span></span> +<span class="line"><span style="color:#24292E">;;</span></span></code></pre> + </div> <p> むしろ、このことがわかっていたからこそ PHP 8.x での動作を要件に課したところがある。 @@ -381,66 +394,74 @@ F. ずばり、文字列同士のビット演算を使う。PHP では、文字列同士でビット演算 (<code>&</code>、<code>|</code>、<code>^</code>) をした場合、文字列の各バイトごとに指定したビット演算がなされ、それを結合したものが演算結果となる。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$a</span> = <span class="hljs-string">"12345"</span>; -<span class="hljs-variable">$b</span> = <span class="hljs-string">"world"</span>; - -<span class="hljs-comment">// $a ^ $b は次のコードと同じ</span> -<span class="hljs-variable">$result</span> = <span class="hljs-string">''</span>; -<span class="hljs-keyword">for</span> (<span class="hljs-variable">$i</span> = <span class="hljs-number">0</span>; <span class="hljs-variable">$i</span> < <span class="hljs-title function_ invoke__">min</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$a</span>), <span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$b</span>)); <span class="hljs-variable">$i</span>++) { -<span class="hljs-variable">$result</span> .= <span class="hljs-variable">$a</span>[<span class="hljs-variable">$i</span>] ^ <span class="hljs-variable">$b</span>[<span class="hljs-variable">$i</span>]; -} - -<span class="hljs-keyword">echo</span> <span class="hljs-variable">$result</span>; -<span class="hljs-comment">// => F]AXQ</span></code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$a </span><span style="color:#D73A49">=</span><span style="color:#032F62"> "12345"</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$b </span><span style="color:#D73A49">=</span><span style="color:#032F62"> "world"</span><span style="color:#24292E">;</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6A737D">// $a ^ $b は次のコードと同じ</span></span> +<span class="line"><span style="color:#24292E">$result </span><span style="color:#D73A49">=</span><span style="color:#032F62"> ''</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">for</span><span style="color:#24292E"> ($i </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">; $i </span><span style="color:#D73A49"><</span><span style="color:#005CC5"> min</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($a), </span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($b)); $i</span><span style="color:#D73A49">++</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#24292E">$result </span><span style="color:#D73A49">.=</span><span style="color:#24292E"> $a[$i] </span><span style="color:#D73A49">^</span><span style="color:#24292E"> $b[$i];</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5">echo</span><span style="color:#24292E"> $result;</span></span> +<span class="line"><span style="color:#6A737D">// => F]AXQ</span></span></code></pre> + </div> <p> これを踏まえ、次のコードを見てみよう。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$x</span> = <span class="hljs-string">"x\nOm\n"</span>; -<span class="hljs-variable">$y</span> = <span class="hljs-string">"\nk!\no"</span>; -<span class="hljs-variable">$r</span> = <span class="hljs-variable">$x</span> ^ <span class="hljs-variable">$y</span>; -<span class="hljs-keyword">echo</span> <span class="hljs-string">"<span class="hljs-subst">$r</span>\n"</span>;</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$x </span><span style="color:#D73A49">=</span><span style="color:#032F62"> "x</span><span style="color:#005CC5">\n</span><span style="color:#032F62">Om</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$y </span><span style="color:#D73A49">=</span><span style="color:#032F62"> "</span><span style="color:#005CC5">\n</span><span style="color:#032F62">k!</span><span style="color:#005CC5">\n</span><span style="color:#032F62">o"</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$r </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $x </span><span style="color:#D73A49">^</span><span style="color:#24292E"> $y;</span></span> +<span class="line"><span style="color:#005CC5">echo</span><span style="color:#032F62"> "</span><span style="color:#24292E">$r</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">;</span></span></code></pre> + </div> <p> 実行すると、<code>range</code> が表示される。さて、PHP では文字列リテラル中に生の改行を直接書いてもよいのだった (「主な障害」の節を参照のこと)。書きかえてみよう。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$x</span> -=<span class="hljs-string">'x -Om -'</span>; -<span class="hljs-variable">$y</span> -=<span class="hljs-string">' -k! -o'</span> -; - -<span class="hljs-variable">$r</span> = <span class="hljs-variable">$x</span> ^ <span class="hljs-variable">$y</span>; -<span class="hljs-keyword">echo</span> <span class="hljs-string">"<span class="hljs-subst">$r</span>\n"</span>;</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$x</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#032F62">'x</span></span> +<span class="line"><span style="color:#032F62">Om</span></span> +<span class="line"><span style="color:#032F62">'</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$y</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#032F62">'</span></span> +<span class="line"><span style="color:#032F62">k!</span></span> +<span class="line"><span style="color:#032F62">o'</span></span> +<span class="line"><span style="color:#24292E">;</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">$r </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $x </span><span style="color:#D73A49">^</span><span style="color:#24292E"> $y;</span></span> +<span class="line"><span style="color:#005CC5">echo</span><span style="color:#032F62"> "</span><span style="color:#24292E">$r</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">;</span></span></code></pre> + </div> <p> さらに <code>#</code> を使って適当に調整すると、次のようになる。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$x</span> -=<span class="hljs-comment">#</span> -<span class="hljs-string">'x -Om -'</span>; -<span class="hljs-variable">$y</span> -=<span class="hljs-string">' -k! -o'</span> -;<span class="hljs-comment">#</span> -<span class="hljs-variable">$r</span> -=<span class="hljs-comment">#</span> -<span class="hljs-variable">$x</span> -^<span class="hljs-comment">#</span> -<span class="hljs-variable">$y</span> -;<span class="hljs-comment">#</span> - -<span class="hljs-keyword">echo</span> <span class="hljs-string">"<span class="hljs-subst">$r</span>\n"</span>;</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$x</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#032F62">'x</span></span> +<span class="line"><span style="color:#032F62">Om</span></span> +<span class="line"><span style="color:#032F62">'</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$y</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#032F62">'</span></span> +<span class="line"><span style="color:#032F62">k!</span></span> +<span class="line"><span style="color:#032F62">o'</span></span> +<span class="line"><span style="color:#24292E">;</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$r</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$x</span></span> +<span class="line"><span style="color:#D73A49">^</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$y</span></span> +<span class="line"><span style="color:#24292E">;</span><span style="color:#6A737D">#</span></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5">echo</span><span style="color:#032F62"> "</span><span style="color:#24292E">$r</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">;</span></span></code></pre> + </div> <p> 1行あたり2文字で、<code>range</code> という文字列を生成することに成功した。他の必要な文字列にも、同様の処理をほどこす。 @@ -458,155 +479,157 @@ o'</span> 完成したものがこちら。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> - -<span class="hljs-variable">$x</span> -=<span class="hljs-comment">#</span> -<span class="hljs-string">'i -S'</span> -;; -<span class="hljs-variable">$y</span> -=<span class="hljs-string">' -b! -'</span>; -<span class="hljs-variable">$c</span> -=<span class="hljs-comment">#</span> -<span class="hljs-variable">$x</span> -^<span class="hljs-comment">#</span> -<span class="hljs-variable">$y</span> -;<span class="hljs-comment">#</span> -<span class="hljs-variable">$x</span> -=<span class="hljs-comment">#</span> -<span class="hljs-string">'x -Om -'</span>; -<span class="hljs-variable">$y</span> -=<span class="hljs-string">' -k! -o'</span> -;<span class="hljs-comment">#</span> -<span class="hljs-variable">$r</span> -=<span class="hljs-comment">#</span> -<span class="hljs-variable">$x</span> -^<span class="hljs-comment">#</span> -<span class="hljs-variable">$y</span> -;<span class="hljs-comment">#</span> -<span class="hljs-variable">$x</span> -=<span class="hljs-comment">#</span> -<span class="hljs-string">'k -Sk -~} -Ma -'</span>; -<span class="hljs-variable">$y</span> -=<span class="hljs-string">' -x! -s! -k! -'</span>; -<span class="hljs-variable">$w</span> -=<span class="hljs-comment">#</span> -<span class="hljs-variable">$x</span> -^<span class="hljs-comment">#</span> -<span class="hljs-variable">$y</span> -;<span class="hljs-comment">#</span> -<span class="hljs-variable">$x</span> -=<span class="hljs-comment">#</span> -<span class="hljs-string">'z -Hd -G'</span> -;<span class="hljs-comment">#</span> -<span class="hljs-variable">$y</span> -=<span class="hljs-string">' -x! -~! -'</span>; -<span class="hljs-variable">$p</span> -=<span class="hljs-comment">#</span> -<span class="hljs-variable">$x</span> -^<span class="hljs-comment">#</span> -<span class="hljs-variable">$y</span> -;<span class="hljs-comment">#</span> -<span class="hljs-variable">$x</span> -=<span class="hljs-comment">#</span> -<span class="hljs-string">'L -[p -'</span>; -<span class="hljs-variable">$y</span> -=<span class="hljs-string">' -c! -'</span>; -<span class="hljs-variable">$f</span> -=<span class="hljs-comment">#</span> -<span class="hljs-variable">$x</span> -^<span class="hljs-comment">#</span> -<span class="hljs-variable">$y</span> -;<span class="hljs-comment">#</span> -<span class="hljs-variable">$x</span> -=<span class="hljs-comment">#</span> -<span class="hljs-string">'H -[p -'</span>; -<span class="hljs-variable">$y</span> -=<span class="hljs-string">' -_! -'</span>; -<span class="hljs-variable">$b</span> -=<span class="hljs-comment">#</span> -<span class="hljs-variable">$x</span> -^<span class="hljs-comment">#</span> -<span class="hljs-variable">$y</span> -;<span class="hljs-comment">#</span> -<span class="hljs-variable">$b</span> -[<span class="hljs-number">1</span> -]= -<span class="hljs-variable">$c</span> -(<span class="hljs-comment">#</span> -<span class="hljs-number">13</span> -*<span class="hljs-number">9</span> -); -<span class="hljs-variable">$s</span> -=<span class="hljs-comment">#</span> -<span class="hljs-variable">$r</span> -(<span class="hljs-number">1</span> -,( -<span class="hljs-number">10</span> -** -<span class="hljs-number">2</span>) -); -<span class="hljs-variable">$w</span> -(<span class="hljs-comment">#</span> -<span class="hljs-variable">$s</span> -,<span class="hljs-comment">#</span> -<span class="hljs-function"><span class="hljs-keyword">fn</span> -(<span class="hljs-params"># -<span class="hljs-variable">$i</span> -</span>)# -=></span> -<span class="hljs-variable">$p</span> -(( -(<span class="hljs-comment">#</span> -<span class="hljs-variable">$i</span> -%<span class="hljs-number">3</span> -?<span class="hljs-comment">#</span> -<span class="hljs-string">''</span> -:<span class="hljs-comment">#</span> -<span class="hljs-variable">$f</span> -). -(<span class="hljs-comment">#</span> -<span class="hljs-variable">$i</span> -%<span class="hljs-number">5</span> -?<span class="hljs-comment">#</span> -<span class="hljs-string">''</span> -:<span class="hljs-comment">#</span> -<span class="hljs-variable">$b</span> -)? -:<span class="hljs-comment">#</span> -<span class="hljs-variable">$i</span> -)<span class="hljs-comment">#</span> -.<span class="hljs-string">' -'</span>) -);</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">$x</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#032F62">'i</span></span> +<span class="line"><span style="color:#032F62">S'</span></span> +<span class="line"><span style="color:#24292E">;;</span></span> +<span class="line"><span style="color:#24292E">$y</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#032F62">'</span></span> +<span class="line"><span style="color:#032F62">b!</span></span> +<span class="line"><span style="color:#032F62">'</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$c</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$x</span></span> +<span class="line"><span style="color:#D73A49">^</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$y</span></span> +<span class="line"><span style="color:#24292E">;</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$x</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#032F62">'x</span></span> +<span class="line"><span style="color:#032F62">Om</span></span> +<span class="line"><span style="color:#032F62">'</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$y</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#032F62">'</span></span> +<span class="line"><span style="color:#032F62">k!</span></span> +<span class="line"><span style="color:#032F62">o'</span></span> +<span class="line"><span style="color:#24292E">;</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$r</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$x</span></span> +<span class="line"><span style="color:#D73A49">^</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$y</span></span> +<span class="line"><span style="color:#24292E">;</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$x</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#032F62">'k</span></span> +<span class="line"><span style="color:#032F62">Sk</span></span> +<span class="line"><span style="color:#032F62">~}</span></span> +<span class="line"><span style="color:#032F62">Ma</span></span> +<span class="line"><span style="color:#032F62">'</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$y</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#032F62">'</span></span> +<span class="line"><span style="color:#032F62">x!</span></span> +<span class="line"><span style="color:#032F62">s!</span></span> +<span class="line"><span style="color:#032F62">k!</span></span> +<span class="line"><span style="color:#032F62">'</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$w</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$x</span></span> +<span class="line"><span style="color:#D73A49">^</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$y</span></span> +<span class="line"><span style="color:#24292E">;</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$x</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#032F62">'z</span></span> +<span class="line"><span style="color:#032F62">Hd</span></span> +<span class="line"><span style="color:#032F62">G'</span></span> +<span class="line"><span style="color:#24292E">;</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$y</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#032F62">'</span></span> +<span class="line"><span style="color:#032F62">x!</span></span> +<span class="line"><span style="color:#032F62">~!</span></span> +<span class="line"><span style="color:#032F62">'</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$p</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$x</span></span> +<span class="line"><span style="color:#D73A49">^</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$y</span></span> +<span class="line"><span style="color:#24292E">;</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$x</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#032F62">'L</span></span> +<span class="line"><span style="color:#032F62">[p</span></span> +<span class="line"><span style="color:#032F62">'</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$y</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#032F62">'</span></span> +<span class="line"><span style="color:#032F62">c!</span></span> +<span class="line"><span style="color:#032F62">'</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$f</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$x</span></span> +<span class="line"><span style="color:#D73A49">^</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$y</span></span> +<span class="line"><span style="color:#24292E">;</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$x</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#032F62">'H</span></span> +<span class="line"><span style="color:#032F62">[p</span></span> +<span class="line"><span style="color:#032F62">'</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$y</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#032F62">'</span></span> +<span class="line"><span style="color:#032F62">_!</span></span> +<span class="line"><span style="color:#032F62">'</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$b</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$x</span></span> +<span class="line"><span style="color:#D73A49">^</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$y</span></span> +<span class="line"><span style="color:#24292E">;</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$b</span></span> +<span class="line"><span style="color:#24292E">[</span><span style="color:#005CC5">1</span></span> +<span class="line"><span style="color:#24292E">]</span><span style="color:#D73A49">=</span></span> +<span class="line"><span style="color:#24292E">$c</span></span> +<span class="line"><span style="color:#24292E">(</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#005CC5">13</span></span> +<span class="line"><span style="color:#D73A49">*</span><span style="color:#005CC5">9</span></span> +<span class="line"><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E">$s</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$r</span></span> +<span class="line"><span style="color:#24292E">(</span><span style="color:#005CC5">1</span></span> +<span class="line"><span style="color:#24292E">,(</span></span> +<span class="line"><span style="color:#005CC5">10</span></span> +<span class="line"><span style="color:#D73A49">**</span></span> +<span class="line"><span style="color:#005CC5">2</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E">$w</span></span> +<span class="line"><span style="color:#24292E">(</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$s</span></span> +<span class="line"><span style="color:#24292E">,</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#005CC5">fn</span></span> +<span class="line"><span style="color:#24292E">(</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$i</span></span> +<span class="line"><span style="color:#24292E">)</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#D73A49">=></span></span> +<span class="line"><span style="color:#24292E">$p</span></span> +<span class="line"><span style="color:#24292E">((</span></span> +<span class="line"><span style="color:#24292E">(</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$i</span></span> +<span class="line"><span style="color:#D73A49">%</span><span style="color:#005CC5">3</span></span> +<span class="line"><span style="color:#D73A49">?</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#032F62">''</span></span> +<span class="line"><span style="color:#D73A49">:</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$f</span></span> +<span class="line"><span style="color:#24292E">)</span><span style="color:#D73A49">.</span></span> +<span class="line"><span style="color:#24292E">(</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$i</span></span> +<span class="line"><span style="color:#D73A49">%</span><span style="color:#005CC5">5</span></span> +<span class="line"><span style="color:#D73A49">?</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#032F62">''</span></span> +<span class="line"><span style="color:#D73A49">:</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$b</span></span> +<span class="line"><span style="color:#24292E">)</span><span style="color:#D73A49">?</span></span> +<span class="line"><span style="color:#D73A49">:</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$i</span></span> +<span class="line"><span style="color:#24292E">)</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#D73A49">.</span><span style="color:#032F62">'</span></span> +<span class="line"><span style="color:#032F62">'</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#24292E">);</span></span></code></pre> + </div> </section> <section id="section--outro"> @@ -626,18 +649,20 @@ _! PHP では、バッククォートを使ってシェルを呼び出せる。これは <code>shell_exec</code> 関数と等価である。さて、PHP ではバックスラッシュによる行継続が使えないと書いたが、シェルでは使える (当然だが、呼び出されるシェルに依存する。Bash なら大丈夫だろう。知らんけど)。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> - -<span class="hljs-title function_ invoke__">printf</span>(` -e\ -c\ -h\ -o\ -\ -<span class="hljs-number">1</span>\ -<span class="hljs-number">2</span>\ -<span class="hljs-number">3</span>\ -`);</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5">printf</span><span style="color:#24292E">(</span><span style="color:#032F62">`</span></span> +<span class="line"><span style="color:#032F62">e\</span></span> +<span class="line"><span style="color:#032F62">c\</span></span> +<span class="line"><span style="color:#032F62">h\</span></span> +<span class="line"><span style="color:#032F62">o\</span></span> +<span class="line"><span style="color:#032F62">\</span></span> +<span class="line"><span style="color:#032F62">1\</span></span> +<span class="line"><span style="color:#032F62">2\</span></span> +<span class="line"><span style="color:#032F62">3\</span></span> +<span class="line"><span style="color:#032F62">`</span><span style="color:#24292E">);</span></span></code></pre> + </div> <p> なお、ここでは簡単のため出力に <code>printf</code> をそのまま使っているが、実際には <code>printf</code> という文字列を合成して可変関数で呼び出す。 @@ -663,56 +688,62 @@ o\ もうこれ以上は不可能だと思っていたのだが、この記事の執筆中に解決する方法を思いついたので載せておく。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> - -<span class="hljs-variable">$c</span> = <span class="hljs-string">'chr'</span>; - -${ -<span class="hljs-string">'_ -'</span>} -=<span class="hljs-comment">#</span> -<span class="hljs-variable">$c</span> -(<span class="hljs-comment">#</span> -<span class="hljs-number">32</span> -). -<span class="hljs-variable">$c</span> -(<span class="hljs-comment">#</span> -<span class="hljs-number">92</span> -); - -<span class="hljs-title function_ invoke__">printf</span>(` -e\ -c\ -h\ -o\ -${ -<span class="hljs-string">'_ -'</span>} -<span class="hljs-number">1</span>\ -<span class="hljs-number">2</span>\ -<span class="hljs-number">3</span>\ -`);</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">$c </span><span style="color:#D73A49">=</span><span style="color:#032F62"> 'chr'</span><span style="color:#24292E">;</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">${</span></span> +<span class="line"><span style="color:#032F62">'_</span></span> +<span class="line"><span style="color:#032F62">'</span><span style="color:#24292E">}</span></span> +<span class="line"><span style="color:#D73A49">=</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#24292E">$c</span></span> +<span class="line"><span style="color:#24292E">(</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#005CC5">32</span></span> +<span class="line"><span style="color:#24292E">)</span><span style="color:#D73A49">.</span></span> +<span class="line"><span style="color:#24292E">$c</span></span> +<span class="line"><span style="color:#24292E">(</span><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#005CC5">92</span></span> +<span class="line"><span style="color:#24292E">);</span></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5">printf</span><span style="color:#24292E">(</span><span style="color:#032F62">`</span></span> +<span class="line"><span style="color:#032F62">e\</span></span> +<span class="line"><span style="color:#032F62">c\</span></span> +<span class="line"><span style="color:#032F62">h\</span></span> +<span class="line"><span style="color:#032F62">o\</span></span> +<span class="line"><span style="color:#032F62">${</span></span> +<span class="line"><span style="color:#032F62">'_</span></span> +<span class="line"><span style="color:#032F62">'}</span></span> +<span class="line"><span style="color:#032F62">1\</span></span> +<span class="line"><span style="color:#032F62">2\</span></span> +<span class="line"><span style="color:#032F62">3\</span></span> +<span class="line"><span style="color:#032F62">`</span><span style="color:#24292E">);</span></span></code></pre> + </div> <p> 先程と同じく、<code>chr</code> や <code>printf</code> を生成する部分は長くなるので省いた。 </p> - <pre class="highlight"><code>${ -'_ -'}</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>${</span></span> +<span class="line"><span>'_</span></span> +<span class="line"><span>'}</span></span></code></pre> + </div> <p> は変数で、中にはスペースとエスケープが入っている (<code>chr(32) . chr(92)</code>)。シェルに渡されている文字列は次のようになる。 </p> - <pre class="highlight"><code>e\ -c\ -h\ -o\ -\ -1\ -2\ -3\</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>e\</span></span> +<span class="line"><span>c\</span></span> +<span class="line"><span>h\</span></span> +<span class="line"><span>o\</span></span> +<span class="line"><span>\</span></span> +<span class="line"><span>1\</span></span> +<span class="line"><span>2\</span></span> +<span class="line"><span>3\</span></span></code></pre> + </div> <p> これは、前掲したコマンドと同じだ。かくして、スペースを陽に書かずにシェルをおおよそ自由に扱えるようになった。Fizzbuzz のワンライナーくらいすぐ書けるだろうから、あとはなんとかなるだろう (試してないけど)。 @@ -726,9 +757,11 @@ o\ ちなみに、PHP 8.2 からは、この記法で Warning が出るようになるようだ。 </p> - <pre class="highlight"><code>${ -'_ -'}</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>${</span></span> +<span class="line"><span>'_</span></span> +<span class="line"><span>'}</span></span></code></pre> + </div> <p> 最新版で警告が出るというのも美しくないので、私としては本編の解法を推す。 diff --git a/vhosts/blog/public/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/index.html b/vhosts/blog/public/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/index.html index 8d72a4f2..efc80674 100644 --- a/vhosts/blog/public/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/index.html +++ b/vhosts/blog/public/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>PHPerKaigi 2023: ボツになったトークン問題 その 1|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -86,27 +85,29 @@ 注意: これはボツ問なので、得られたトークンを PHPerKaigi で入力してもポイントにはならない。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> - -$π = <span class="hljs-variable">$argv</span>[<span class="hljs-number">1</span>] ?? <span class="hljs-literal">null</span>; -<span class="hljs-keyword">if</span> ($π === <span class="hljs-literal">null</span>) { - <span class="hljs-keyword">exit</span>(<span class="hljs-string">'No input.'</span>); -} -$π = <span class="hljs-title function_ invoke__">trim</span>($π); -<span class="hljs-keyword">if</span> (!<span class="hljs-title function_ invoke__">is_numeric</span>($π)) { - <span class="hljs-keyword">exit</span>(<span class="hljs-string">'Invalid input.'</span>); -} - -<span class="hljs-variable">$s</span> = <span class="hljs-title function_ invoke__">implode</span>(<span class="hljs-title function_ invoke__">array_map</span>(<span class="hljs-title function_ invoke__">chr</span>(...), <span class="hljs-title function_ invoke__">str_split</span>($π, <span class="hljs-number">2</span>))); - -<span class="hljs-title function_ invoke__">preg_match</span>(<span class="hljs-string">'/(\x23.+?) /'</span>, <span class="hljs-variable">$s</span>, <span class="hljs-variable">$m</span>); -<span class="hljs-variable">$t</span> = <span class="hljs-variable">$m</span>[<span class="hljs-number">1</span>] ?? <span class="hljs-string">''</span>; - -<span class="hljs-keyword">if</span> (<span class="hljs-title function_ invoke__">md5</span>(<span class="hljs-variable">$t</span>) === <span class="hljs-string">'056e831a4146bf123e8ea16613303d2e'</span>) { - <span class="hljs-keyword">echo</span> <span class="hljs-string">"Token: <span class="hljs-subst">{$t}</span>\n"</span>; -} <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">echo</span> <span class="hljs-string">"Failed.\n"</span>; -}</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">$π </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $argv[</span><span style="color:#005CC5">1</span><span style="color:#24292E">] </span><span style="color:#D73A49">??</span><span style="color:#005CC5"> null</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">if</span><span style="color:#24292E"> ($π </span><span style="color:#D73A49">===</span><span style="color:#005CC5"> null</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#D73A49"> exit</span><span style="color:#24292E">(</span><span style="color:#032F62">'No input.'</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"><span style="color:#24292E">$π </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> trim</span><span style="color:#24292E">($π);</span></span> +<span class="line"><span style="color:#D73A49">if</span><span style="color:#24292E"> (</span><span style="color:#D73A49">!</span><span style="color:#005CC5">is_numeric</span><span style="color:#24292E">($π)) {</span></span> +<span class="line"><span style="color:#D73A49"> exit</span><span style="color:#24292E">(</span><span style="color:#032F62">'Invalid input.'</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">$s </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> implode</span><span style="color:#24292E">(</span><span style="color:#005CC5">array_map</span><span style="color:#24292E">(</span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#D73A49">...</span><span style="color:#24292E">), </span><span style="color:#005CC5">str_split</span><span style="color:#24292E">($π, </span><span style="color:#005CC5">2</span><span style="color:#24292E">)));</span></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5">preg_match</span><span style="color:#24292E">(</span><span style="color:#032F62">'/(</span><span style="color:#22863A;font-weight:bold">\x</span><span style="color:#032F62">23.</span><span style="color:#D73A49">+</span><span style="color:#032F62">?) /'</span><span style="color:#24292E">, $s, $m);</span></span> +<span class="line"><span style="color:#24292E">$t </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $m[</span><span style="color:#005CC5">1</span><span style="color:#24292E">] </span><span style="color:#D73A49">??</span><span style="color:#032F62"> ''</span><span style="color:#24292E">;</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">if</span><span style="color:#24292E"> (</span><span style="color:#005CC5">md5</span><span style="color:#24292E">($t) </span><span style="color:#D73A49">===</span><span style="color:#032F62"> '056e831a4146bf123e8ea16613303d2e'</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#005CC5"> echo</span><span style="color:#032F62"> "Token: {</span><span style="color:#24292E">$t</span><span style="color:#032F62">}</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">} </span><span style="color:#D73A49">else</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#005CC5"> echo</span><span style="color:#032F62"> "Failed.</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> </section> <section id="section--how-to-obtain-token"> @@ -115,15 +116,19 @@ $π = <span class="hljs-title function_ invoke__">trim</span>($π); ソースを見るとわかるとおり、<code>$argv[1]</code> を参照している。それを <code>$π</code> なる変数に代入しているので、円周率を渡してみる。 </p> - <pre class="highlight" language="shell-session"><code>$ php Q.php 3.14 -Failed.</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ php Q.php 3.14</span></span> +<span class="line"><span>Failed.</span></span></code></pre> + </div> <p> 失敗してしまった。精度を上げてみる。 </p> - <pre class="highlight" language="shell-session"><code>$ php Q.php 3.1415 -Failed.</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ php Q.php 3.1415</span></span> +<span class="line"><span>Failed.</span></span></code></pre> + </div> <p> だめだった。これを成功するまで繰り返す。 @@ -133,8 +138,10 @@ Failed.</code></pre> 最初にトークンが得られるのは、小数点以下 16 桁目まで入力したときで、こうなる。 </p> - <pre class="highlight" language="shell-session"><code>$ php Q.php 3.1415926535897932 -Token: #YO</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ php Q.php 3.1415926535897932</span></span> +<span class="line"><span>Token: #YO</span></span></code></pre> + </div> <p> めでたくトークン「<code>#YO</code>」が手に入った。 @@ -147,20 +154,24 @@ Token: #YO</code></pre> 短いので頭から追っていく。 </p> - <pre class="highlight" language="php"><code class="highlight">$π = <span class="hljs-variable">$argv</span>[<span class="hljs-number">1</span>] ?? <span class="hljs-literal">null</span>; -<span class="hljs-keyword">if</span> ($π === <span class="hljs-literal">null</span>) { - <span class="hljs-keyword">exit</span>(<span class="hljs-string">'No input.'</span>); -} -$π = <span class="hljs-title function_ invoke__">trim</span>($π); -<span class="hljs-keyword">if</span> (!<span class="hljs-title function_ invoke__">is_numeric</span>($π)) { - <span class="hljs-keyword">exit</span>(<span class="hljs-string">'Invalid input.'</span>); -}</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$π </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $argv[</span><span style="color:#005CC5">1</span><span style="color:#24292E">] </span><span style="color:#D73A49">??</span><span style="color:#005CC5"> null</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">if</span><span style="color:#24292E"> ($π </span><span style="color:#D73A49">===</span><span style="color:#005CC5"> null</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#D73A49"> exit</span><span style="color:#24292E">(</span><span style="color:#032F62">'No input.'</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"><span style="color:#24292E">$π </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> trim</span><span style="color:#24292E">($π);</span></span> +<span class="line"><span style="color:#D73A49">if</span><span style="color:#24292E"> (</span><span style="color:#D73A49">!</span><span style="color:#005CC5">is_numeric</span><span style="color:#24292E">($π)) {</span></span> +<span class="line"><span style="color:#D73A49"> exit</span><span style="color:#24292E">(</span><span style="color:#032F62">'Invalid input.'</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> 入力のバリデーション部分。数値のみ受け付ける。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$s</span> = <span class="hljs-title function_ invoke__">implode</span>(<span class="hljs-title function_ invoke__">array_map</span>(<span class="hljs-title function_ invoke__">chr</span>(...), <span class="hljs-title function_ invoke__">str_split</span>($π, <span class="hljs-number">2</span>)));</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$s </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> implode</span><span style="color:#24292E">(</span><span style="color:#005CC5">array_map</span><span style="color:#24292E">(</span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#D73A49">...</span><span style="color:#24292E">), </span><span style="color:#005CC5">str_split</span><span style="color:#24292E">($π, </span><span style="color:#005CC5">2</span><span style="color:#24292E">)));</span></span></code></pre> + </div> <p> <code>$π</code> を 2 文字ごとに区切り (<code>str_split</code>)、数値を ASCII コードと見做して文字に変換 (<code>chr</code>) して結合 (<code>implode</code>) している。 @@ -170,13 +181,17 @@ $π = <span class="hljs-title function_ invoke__">trim</span>($π); 例えば、<code>$π</code> が <code>'656667'</code> だったとすると、<code>65</code>、<code>66</code>、<code>67</code> に対応した <code>'A'</code>、<code>'B'</code>、<code>'C'</code> へと変換され、<code>'ABC'</code> になる。 </p> - <pre class="highlight" language="php"><code class="highlight">$π = <span class="hljs-string">'656667'</span>; -<span class="hljs-variable">$s</span> = <span class="hljs-title function_ invoke__">implode</span>(<span class="hljs-title function_ invoke__">array_map</span>(<span class="hljs-title function_ invoke__">chr</span>(...), <span class="hljs-title function_ invoke__">str_split</span>($π, <span class="hljs-number">2</span>))); -<span class="hljs-keyword">echo</span> <span class="hljs-variable">$s</span>; -<span class="hljs-comment">// => ABC</span></code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$π </span><span style="color:#D73A49">=</span><span style="color:#032F62"> '656667'</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$s </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> implode</span><span style="color:#24292E">(</span><span style="color:#005CC5">array_map</span><span style="color:#24292E">(</span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#D73A49">...</span><span style="color:#24292E">), </span><span style="color:#005CC5">str_split</span><span style="color:#24292E">($π, </span><span style="color:#005CC5">2</span><span style="color:#24292E">)));</span></span> +<span class="line"><span style="color:#005CC5">echo</span><span style="color:#24292E"> $s;</span></span> +<span class="line"><span style="color:#6A737D">// => ABC</span></span></code></pre> + </div> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-title function_ invoke__">preg_match</span>(<span class="hljs-string">'/(\x23.+?) /'</span>, <span class="hljs-variable">$s</span>, <span class="hljs-variable">$m</span>); -<span class="hljs-variable">$t</span> = <span class="hljs-variable">$m</span>[<span class="hljs-number">1</span>] ?? <span class="hljs-string">''</span>;</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#005CC5">preg_match</span><span style="color:#24292E">(</span><span style="color:#032F62">'/(</span><span style="color:#22863A;font-weight:bold">\x</span><span style="color:#032F62">23.</span><span style="color:#D73A49">+</span><span style="color:#032F62">?) /'</span><span style="color:#24292E">, $s, $m);</span></span> +<span class="line"><span style="color:#24292E">$t </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $m[</span><span style="color:#005CC5">1</span><span style="color:#24292E">] </span><span style="color:#D73A49">??</span><span style="color:#032F62"> ''</span><span style="color:#24292E">;</span></span></code></pre> + </div> <p> 正規表現でマッチングしている。<code>\x23</code> は <code>#</code> と同じであることに留意すると、この正規表現は「<code>#</code> から始まる 2 以上の長さ (含 <code>#</code>) の文字列で、最初に現れるスペースまで」にマッチする。つまりこれは、PHPerKaigi におけるトークンである。 @@ -186,11 +201,13 @@ $π = <span class="hljs-title function_ invoke__">trim</span>($π); なお、<code>#</code> を直接書いていないのは、<code>/#.+?) /</code> と書くと、<code>#.+?)</code> という意図せぬトークンが登録されてしまうからである。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-keyword">if</span> (<span class="hljs-title function_ invoke__">md5</span>(<span class="hljs-variable">$t</span>) === <span class="hljs-string">'056e831a4146bf123e8ea16613303d2e'</span>) { - <span class="hljs-keyword">echo</span> <span class="hljs-string">"Token: <span class="hljs-subst">{$t}</span>\n"</span>; -} <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">echo</span> <span class="hljs-string">"Failed.\n"</span>; -}</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">if</span><span style="color:#24292E"> (</span><span style="color:#005CC5">md5</span><span style="color:#24292E">($t) </span><span style="color:#D73A49">===</span><span style="color:#032F62"> '056e831a4146bf123e8ea16613303d2e'</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#005CC5"> echo</span><span style="color:#032F62"> "Token: {</span><span style="color:#24292E">$t</span><span style="color:#032F62">}</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">} </span><span style="color:#D73A49">else</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#005CC5"> echo</span><span style="color:#032F62"> "Failed.</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> 最後にトークンのハッシュ値を見て、想定解かどうかを確認する。 diff --git a/vhosts/blog/public/posts/2022-10-28/setup-server-for-this-site/index.html b/vhosts/blog/public/posts/2022-10-28/setup-server-for-this-site/index.html index e6644a58..cce709ac 100644 --- a/vhosts/blog/public/posts/2022-10-28/setup-server-for-this-site/index.html +++ b/vhosts/blog/public/posts/2022-10-28/setup-server-for-this-site/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>【備忘録】 このサイト用の VPS をセットアップしたときのメモ|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -94,8 +93,10 @@ ローカルマシンで鍵を生成する。 </p> - <pre class="highlight" language="shell-session"><code>$ ssh-keygen -t ed25519 -b 521 -f ~/.ssh/teika.key -$ ssh-keygen -t ed25519 -b 521 -f ~/.ssh/github2teika.key</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ ssh-keygen -t ed25519 -b 521 -f ~/.ssh/teika.key</span></span> +<span class="line"><span>$ ssh-keygen -t ed25519 -b 521 -f ~/.ssh/github2teika.key</span></span></code></pre> + </div> <p> <code>teika.key</code> はローカルからサーバへの接続用、<code>github2teika.key</code> は、GitHub Actions からサーバへのデプロイ用。 @@ -108,12 +109,14 @@ $ ssh-keygen -t ed25519 -b 521 -f ~/.ssh/github2teika.key</code></pre> <code>.ssh/config</code> に設定しておく。 </p> - <pre class="highlight" language="ssh_config"><code>Host teika - HostName ********** - User ********** - Port ********** - IdentityFile ~/.ssh/teika.key - IdentitiesOnly yes</code></pre> + <div class="codeblock" language="ssh_config"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>Host teika</span></span> +<span class="line"><span> HostName **********</span></span> +<span class="line"><span> User **********</span></span> +<span class="line"><span> Port **********</span></span> +<span class="line"><span> IdentityFile ~/.ssh/teika.key</span></span> +<span class="line"><span> IdentitiesOnly yes</span></span></code></pre> + </div> </section> </section> @@ -132,22 +135,28 @@ $ ssh-keygen -t ed25519 -b 521 -f ~/.ssh/github2teika.key</code></pre> 管理者ユーザで作業すると危ないので、メインで使うユーザを作成する。<code>sudo</code> グループに追加して <code>sudo</code> できるようにし、<code>su</code> で切り替え。 </p> - <pre class="highlight" language="shell-session"><code>$ sudo adduser ********** -$ sudo adduser ********** sudo -$ su ********** -$ cd</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ sudo adduser **********</span></span> +<span class="line"><span>$ sudo adduser ********** sudo</span></span> +<span class="line"><span>$ su **********</span></span> +<span class="line"><span>$ cd</span></span></code></pre> + </div> </section> <section id="section--basic-setup--hostname"> <h3><a href="#section--basic-setup--hostname">ホスト名を変える</a></h3> - <pre class="highlight" language="shell-session"><code>$ sudo hostname teika</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ sudo hostname teika</span></span></code></pre> + </div> </section> <section id="section--basic-setup--public-key"> <h3><a href="#section--basic-setup--public-key">公開鍵を置く</a></h3> - <pre class="highlight" language="shell-session"><code>$ mkdir ~/.ssh -$ chmod 700 ~/.ssh -$ vi ~/.ssh/authorized_keys</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ mkdir ~/.ssh</span></span> +<span class="line"><span>$ chmod 700 ~/.ssh</span></span> +<span class="line"><span>$ vi ~/.ssh/authorized_keys</span></span></code></pre> + </div> <p> <code>authorized_keys</code> には、ローカルで生成した <code>~/.ssh/teika.key.pub</code> と <code>~/.ssh/github2teika.key.pub</code> の内容をコピーする。 @@ -160,8 +169,10 @@ $ vi ~/.ssh/authorized_keys</code></pre> SSH の設定を変更し、少しでも安全にしておく。 </p> - <pre class="highlight" language="shell-session"><code>$ sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak -$ sudo vi /etc/ssh/sshd_config</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak</span></span> +<span class="line"><span>$ sudo vi /etc/ssh/sshd_config</span></span></code></pre> + </div> <ul> <li> @@ -181,8 +192,10 @@ $ sudo vi /etc/ssh/sshd_config</code></pre> そして設定を反映。 </p> - <pre class="highlight" language="shell-session"><code>$ sudo systemctl restart sshd -$ sudo systemctl status sshd</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ sudo systemctl restart sshd</span></span> +<span class="line"><span>$ sudo systemctl status sshd</span></span></code></pre> + </div> </section> <section id="section--basic-setup--ssh-connect"> @@ -191,7 +204,9 @@ $ sudo systemctl status sshd</code></pre> 今の SSH セッションは閉じずに、ターミナルを別途開いて疎通確認する。セッションを閉じてしまうと、SSH の設定に不備があった場合に締め出しをくらう。 </p> - <pre class="highlight" language="shell-session"><code>$ ssh teika</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ ssh teika</span></span></code></pre> + </div> </section> <section id="section--basic-setup--close-ports"> @@ -200,11 +215,13 @@ $ sudo systemctl status sshd</code></pre> デフォルトの 22 番を閉じ、設定したポートだけ空ける。 </p> - <pre class="highlight" language="shell-session"><code>$ sudo ufw deny ssh -$ sudo ufw allow ******* -$ sudo ufw enable -$ sudo ufw reload -$ sudo ufw status</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ sudo ufw deny ssh</span></span> +<span class="line"><span>$ sudo ufw allow *******</span></span> +<span class="line"><span>$ sudo ufw enable</span></span> +<span class="line"><span>$ sudo ufw reload</span></span> +<span class="line"><span>$ sudo ufw status</span></span></code></pre> + </div> <p> ここでもう一度 SSH の接続確認を挟む。 @@ -217,40 +234,50 @@ $ sudo ufw status</code></pre> GitHub に置いてある private リポジトリをサーバから clone したいので、SSH 鍵を生成して置いておく。 </p> - <pre class="highlight" language="shell-session"><code>$ ssh-keygen -t ed25519 -b 521 -f ~/.ssh/github.key -$ cat ~/.ssh/github.key.pub</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ ssh-keygen -t ed25519 -b 521 -f ~/.ssh/github.key</span></span> +<span class="line"><span>$ cat ~/.ssh/github.key.pub</span></span></code></pre> + </div> <p> <a href="https://github.com/settings/ssh" rel="noreferrer" target="_blank">GitHub の設定画面</a> から、この公開鍵を追加する。 </p> - <pre class="highlight" language="shell-session"><code>$ vi ~/.ssh/config</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ vi ~/.ssh/config</span></span></code></pre> + </div> <p> 設定はこう。 </p> - <pre class="highlight" language="ssh_config"><code>Host github.com - HostName github.com - User git - Port 22 - IdentityFile ~/.ssh/github.key - IdentitiesOnly yes</code></pre> + <div class="codeblock" language="ssh_config"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>Host github.com</span></span> +<span class="line"><span> HostName github.com</span></span> +<span class="line"><span> User git</span></span> +<span class="line"><span> Port 22</span></span> +<span class="line"><span> IdentityFile ~/.ssh/github.key</span></span> +<span class="line"><span> IdentitiesOnly yes</span></span></code></pre> + </div> <p> 最後に接続できるか確認しておく。 </p> - <pre class="highlight" language="shell-session"><code>$ ssh -T github.com</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ ssh -T github.com</span></span></code></pre> + </div> </section> <section id="section--basic-setup--upgrade-packages"> <h3><a href="#section--basic-setup--upgrade-packages">パッケージの更新</a></h3> - <pre class="highlight" language="shell-session"><code>$ sudo apt update -$ sudo apt upgrade -$ sudo apt update -$ sudo apt upgrade -$ sudo apt autoremove</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ sudo apt update</span></span> +<span class="line"><span>$ sudo apt upgrade</span></span> +<span class="line"><span>$ sudo apt update</span></span> +<span class="line"><span>$ sudo apt upgrade</span></span> +<span class="line"><span>$ sudo apt autoremove</span></span></code></pre> + </div> </section> </section> @@ -265,12 +292,16 @@ $ sudo apt autoremove</code></pre> <section id="section--site-hosting-setup--install-softwares"> <h3><a href="#section--site-hosting-setup--install-softwares">使うソフトウェアのインストール</a></h3> - <pre class="highlight" language="shell-session"><code>$ sudo apt install docker docker-compose git make</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ sudo apt install docker docker-compose git make</span></span></code></pre> + </div> </section> <section id="section--site-hosting-setup--docker"> <h3><a href="#section--site-hosting-setup--docker">メインユーザが Docker を使えるように</a></h3> - <pre class="highlight" language="shell-session"><code>$ sudo adduser ********** docker</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ sudo adduser ********** docker</span></span></code></pre> + </div> </section> <section id="section--site-hosting-setup--open-http-ports"> @@ -279,29 +310,37 @@ $ sudo apt autoremove</code></pre> 80 番と 443 番を空ける。 </p> - <pre class="highlight" language="shell-session"><code>$ sudo ufw allow 80/tcp -$ sudo ufw allow 443/tcp -$ sudo ufw reload -$ sudo ufw status</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ sudo ufw allow 80/tcp</span></span> +<span class="line"><span>$ sudo ufw allow 443/tcp</span></span> +<span class="line"><span>$ sudo ufw reload</span></span> +<span class="line"><span>$ sudo ufw status</span></span></code></pre> + </div> </section> <section id="section--site-hosting-setup--clone-repositories"> <h3><a href="#section--site-hosting-setup--clone-repositories">リポジトリのクローン</a></h3> - <pre class="highlight" language="shell-session"><code>$ cd -$ git clone git@github.com:nsfisis/nsfisis.dev.git -$ cd nsfisis.dev -$ git submodule update --init</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ cd</span></span> +<span class="line"><span>$ git clone git@github.com:nsfisis/nsfisis.dev.git</span></span> +<span class="line"><span>$ cd nsfisis.dev</span></span> +<span class="line"><span>$ git submodule update --init</span></span></code></pre> + </div> </section> <section id="section--site-hosting-setup--certbot"> <h3><a href="#section--site-hosting-setup--certbot">certbot で証明書取得</a></h3> - <pre class="highlight" language="shell-session"><code>$ docker-compose up -d acme-challenge -$ make setup</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ docker-compose up -d acme-challenge</span></span> +<span class="line"><span>$ make setup</span></span></code></pre> + </div> </section> <section id="section--site-hosting-setup--run-server"> <h3><a href="#section--site-hosting-setup--run-server">サーバを稼動させる</a></h3> - <pre class="highlight" language="shell-session"><code>$ make serve</code></pre> + <div class="codeblock" language="shell-session"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ make serve</span></span></code></pre> + </div> </section> </section> diff --git a/vhosts/blog/public/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2/index.html b/vhosts/blog/public/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2/index.html index 147d7a81..e093f669 100644 --- a/vhosts/blog/public/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2/index.html +++ b/vhosts/blog/public/posts/2022-11-19/phperkaigi-2023-unused-token-quiz-2/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>PHPerKaigi 2023: ボツになったトークン問題 その 2|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -90,16 +89,18 @@ 注意: これはボツ問なので、得られたトークンを PHPerKaigi で入力してもポイントにはならない。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span></code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span></code></pre> + </div> <p> "And Then There Were None" (そして誰もいなくなった) と名付けた作品。変則 quine (自分自身と同じソースコードを出力するプログラム) になっている。 @@ -112,46 +113,52 @@ 実行してみると、次のような出力が得られる。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-comment">#</span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span></code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span></code></pre> + </div> <p> 1 行目を除き、先ほどのコードとほぼ同じものが出てきた。もう一度実行してみる。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-comment">#</span> -W -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span> -<span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">""</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span></code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#005CC5">W</span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span> +<span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">""</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<?php printf((isset($s)?fn($s)=>trim($s,""):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span></code></pre> + </div> <p> 今度は 2 行目が書き換えられた。すべての行が変化するまで繰り返すと次のようになる。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-comment">#</span> -W -E -L -O -V -E -P -H -P</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D">#</span></span> +<span class="line"><span style="color:#005CC5">W</span></span> +<span class="line"><span style="color:#005CC5">E</span></span> +<span class="line"><span style="color:#005CC5">L</span></span> +<span class="line"><span style="color:#005CC5">O</span></span> +<span class="line"><span style="color:#005CC5">V</span></span> +<span class="line"><span style="color:#005CC5">E</span></span> +<span class="line"><span style="color:#005CC5">P</span></span> +<span class="line"><span style="color:#005CC5">H</span></span> +<span class="line"><span style="color:#005CC5">P</span></span></code></pre> + </div> <p> トークン「#WELOVEPHP」が手に入った。 @@ -168,7 +175,9 @@ P</code></pre> Vim で開くと次のようになる (1 行目を抜粋)。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> <span class="hljs-title function_ invoke__">printf</span>((<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$s</span>)?<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-variable">$s</span>,<span class="hljs-string">"<200b>"</span>):<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>))(<span class="hljs-variable">$s</span>=<span class="hljs-string">'<200b><?php printf((isset($s)?fn($s)=>trim($s,"<200b>"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span>).<span class="hljs-string">"\n"</span>,<span class="hljs-string">"\x27<span class="hljs-subst">$s</span>\x27"</span>);<span class="hljs-meta">?></span></code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span><span style="color:#005CC5"> printf</span><span style="color:#24292E">((</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">?fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">trim</span><span style="color:#24292E">($s,</span><span style="color:#032F62">"<200b>"</span><span style="color:#24292E">)</span><span style="color:#D73A49">:fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">))($s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<200b><?php printf((isset($s)?fn($s)=>trim($s,"<200b>"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span><span style="color:#24292E">)</span><span style="color:#D73A49">.</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\x27</span><span style="color:#24292E">$s</span><span style="color:#005CC5">\x27</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span><span style="color:#D73A49">?></span></span></code></pre> + </div> <p> <code><200b></code> と表示されているのは、Unicode の U+200b で、ゼロ幅スペースである。 @@ -193,13 +202,17 @@ P</code></pre> 続いて、トークンへの変換ロジックを解析する。注目すべきはこの部分だ。以下、ゼロ幅スペースは Vim での表示に合わせて <code><200b></code> と記載する。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$s</span></span>)=></span><span class="hljs-title function_ invoke__">chr</span>(<span class="hljs-title function_ invoke__">strlen</span>(<span class="hljs-variable">$s</span>)/<span class="hljs-number">3</span>)</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">fn</span><span style="color:#24292E">($s)=></span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">strlen</span><span style="color:#24292E">($s)</span><span style="color:#D73A49">/</span><span style="color:#005CC5">3</span><span style="color:#24292E">)</span></span></code></pre> + </div> <p> PHP の <code>strlen()</code> は文字列のバイト数を返す。1 行目の <code>$s</code> は以下の内容となっており、 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$s</span>=<span class="hljs-string">'<200b><?php printf((isset($s)?fn($s)=>trim($s,"<200b>"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span></code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$s</span><span style="color:#D73A49">=</span><span style="color:#032F62">'<200b><?php printf((isset($s)?fn($s)=>trim($s,"<200b>"):fn($s)=>chr(strlen($s)/3))($s=%s)."\n","\x27$s\x27");?>'</span></span></code></pre> + </div> <p> このソースコードは UTF-8 で書かれているので、105 バイトになる。それを 3 で割ると 35 となり、これは <code>#</code> の ASCII コードと一致する。他の行も、同様にしてゼロ幅スペースを詰めることで文字列長を調整し、トークンをエンコードしている。 diff --git a/vhosts/blog/public/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3/index.html b/vhosts/blog/public/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3/index.html index 38e6a3f6..6cad79cb 100644 --- a/vhosts/blog/public/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3/index.html +++ b/vhosts/blog/public/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>PHPerKaigi 2023: ボツになったトークン問題 その 3|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -96,118 +95,120 @@ 注意: これはボツ問なので、得られたトークンを PHPerKaigi で入力してもポイントにはならない。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> -<span class="hljs-keyword">try</span> { - <span class="hljs-title function_ invoke__">f</span>(<span class="hljs-title function_ invoke__">g</span>() / <span class="hljs-keyword">__LINE__</span>); -} <span class="hljs-keyword">catch</span> (<span class="hljs-built_in">Throwable</span> <span class="hljs-variable">$e</span>) { - <span class="hljs-keyword">while</span> (<span class="hljs-variable">$e</span> = <span class="hljs-variable">$e</span>-><span class="hljs-title function_ invoke__">getPrevious</span>()) <span class="hljs-title function_ invoke__">printf</span>(<span class="hljs-string">'%c'</span>, <span class="hljs-variable">$e</span>-><span class="hljs-title function_ invoke__">getLine</span>() + <span class="hljs-number">23</span>); - <span class="hljs-keyword">echo</span> <span class="hljs-string">"\n"</span>; -} -<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">f</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> <span class="hljs-variable">$i</span></span>) </span>{ - <span class="hljs-keyword">if</span> (<span class="hljs-variable">$i</span> < <span class="hljs-number">0</span>) <span class="hljs-title function_ invoke__">f</span>(); - <span class="hljs-keyword">try</span> { - <span class="hljs-keyword">match</span> (<span class="hljs-variable">$i</span>) { - <span class="hljs-number">0</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - - - - <span class="hljs-number">15</span>, <span class="hljs-number">36</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - <span class="hljs-number">14</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - <span class="hljs-number">37</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - - - - - - - - - - - <span class="hljs-number">6</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - - <span class="hljs-number">5</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - - <span class="hljs-number">22</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - - - - - <span class="hljs-number">34</span>, <span class="hljs-number">35</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - - - - - - - - - <span class="hljs-number">25</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - <span class="hljs-number">17</span>, <span class="hljs-number">21</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - - <span class="hljs-number">24</span>, <span class="hljs-number">32</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - - - - - - - - <span class="hljs-number">33</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - - <span class="hljs-number">16</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - - - <span class="hljs-number">18</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - - - - - - - - - <span class="hljs-number">7</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - - <span class="hljs-number">2</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - <span class="hljs-number">1</span>, <span class="hljs-number">20</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - <span class="hljs-number">10</span>, <span class="hljs-number">28</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - <span class="hljs-number">8</span>, <span class="hljs-number">12</span>, <span class="hljs-number">26</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - <span class="hljs-number">4</span>, <span class="hljs-number">9</span>, <span class="hljs-number">13</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - - - - - - <span class="hljs-number">31</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - - <span class="hljs-number">29</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - - <span class="hljs-number">11</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - - - - <span class="hljs-number">3</span>, <span class="hljs-number">19</span>, <span class="hljs-number">23</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - - - <span class="hljs-number">27</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - - <span class="hljs-number">30</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - }; - } <span class="hljs-keyword">finally</span> { - <span class="hljs-title function_ invoke__">f</span>(<span class="hljs-variable">$i</span> - <span class="hljs-number">1</span>); - } -} - - - - - - - -<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">g</span>(<span class="hljs-params"></span>) </span>{ - <span class="hljs-keyword">return</span> <span class="hljs-keyword">__LINE__</span>; -}</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> +<span class="line"><span style="color:#D73A49">try</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#6F42C1"> f</span><span style="color:#24292E">(</span><span style="color:#6F42C1">g</span><span style="color:#24292E">() </span><span style="color:#D73A49">/</span><span style="color:#005CC5"> __LINE__</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E">} </span><span style="color:#D73A49">catch</span><span style="color:#24292E"> (</span><span style="color:#005CC5">Throwable</span><span style="color:#24292E"> $e) {</span></span> +<span class="line"><span style="color:#D73A49"> while</span><span style="color:#24292E"> ($e </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $e</span><span style="color:#D73A49">-></span><span style="color:#6F42C1">getPrevious</span><span style="color:#24292E">()) </span><span style="color:#005CC5">printf</span><span style="color:#24292E">(</span><span style="color:#032F62">'%c'</span><span style="color:#24292E">, $e</span><span style="color:#D73A49">-></span><span style="color:#6F42C1">getLine</span><span style="color:#24292E">() </span><span style="color:#D73A49">+</span><span style="color:#005CC5"> 23</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#005CC5"> echo</span><span style="color:#032F62"> "</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"><span style="color:#D73A49">function</span><span style="color:#6F42C1"> f</span><span style="color:#24292E">(</span><span style="color:#D73A49">int</span><span style="color:#24292E"> $i) {</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> ($i </span><span style="color:#D73A49"><</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">) </span><span style="color:#6F42C1">f</span><span style="color:#24292E">();</span></span> +<span class="line"><span style="color:#D73A49"> try</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> match</span><span style="color:#24292E"> ($i) {</span></span> +<span class="line"><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5"> 15</span><span style="color:#24292E">, </span><span style="color:#005CC5">36</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#005CC5"> 14</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#005CC5"> 37</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5"> 6</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5"> 5</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5"> 22</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5"> 34</span><span style="color:#24292E">, </span><span style="color:#005CC5">35</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5"> 25</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#005CC5"> 17</span><span style="color:#24292E">, </span><span style="color:#005CC5">21</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5"> 24</span><span style="color:#24292E">, </span><span style="color:#005CC5">32</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5"> 33</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5"> 16</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5"> 18</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5"> 7</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5"> 2</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#005CC5"> 1</span><span style="color:#24292E">, </span><span style="color:#005CC5">20</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#005CC5"> 10</span><span style="color:#24292E">, </span><span style="color:#005CC5">28</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#005CC5"> 8</span><span style="color:#24292E">, </span><span style="color:#005CC5">12</span><span style="color:#24292E">, </span><span style="color:#005CC5">26</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#005CC5"> 4</span><span style="color:#24292E">, </span><span style="color:#005CC5">9</span><span style="color:#24292E">, </span><span style="color:#005CC5">13</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5"> 31</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5"> 29</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5"> 11</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5"> 3</span><span style="color:#24292E">, </span><span style="color:#005CC5">19</span><span style="color:#24292E">, </span><span style="color:#005CC5">23</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5"> 27</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5"> 30</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E"> };</span></span> +<span class="line"><span style="color:#24292E"> } </span><span style="color:#D73A49">finally</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#6F42C1"> f</span><span style="color:#24292E">($i </span><span style="color:#D73A49">-</span><span style="color:#005CC5"> 1</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">function</span><span style="color:#6F42C1"> g</span><span style="color:#24292E">() {</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#005CC5"> __LINE__</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> "Catchline" と名付けた作品。実行するとトークン <code>#base64_decode('SGVsbG8sIFdvcmxkIQ==')</code> が得られる。 @@ -247,20 +248,22 @@ このうち 1つ目のケースは、 <code>finally</code> 節の中でエラーを投げると PHP 処理系が勝手に <code>$previous</code> を設定してくれる。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> - -<span class="hljs-keyword">try</span> { - <span class="hljs-keyword">try</span> { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Exception</span>(<span class="hljs-string">"Error 1"</span>); - } <span class="hljs-keyword">finally</span> { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Exception</span>(<span class="hljs-string">"Error 2"</span>); - } -} <span class="hljs-keyword">catch</span> (<span class="hljs-built_in">Exception</span> <span class="hljs-variable">$e</span>) { - <span class="hljs-keyword">echo</span> <span class="hljs-variable">$e</span>-><span class="hljs-title function_ invoke__">getMessage</span>() . PHP_EOL; - <span class="hljs-comment">// => Error 2</span> - <span class="hljs-keyword">echo</span> <span class="hljs-variable">$e</span>-><span class="hljs-title function_ invoke__">getPrevious</span>()-><span class="hljs-title function_ invoke__">getMessage</span>() . PHP_EOL; - <span class="hljs-comment">// => Error 1</span> -}</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">try</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> try</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> throw</span><span style="color:#D73A49"> new</span><span style="color:#005CC5"> Exception</span><span style="color:#24292E">(</span><span style="color:#032F62">"Error 1"</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E"> } </span><span style="color:#D73A49">finally</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> throw</span><span style="color:#D73A49"> new</span><span style="color:#005CC5"> Exception</span><span style="color:#24292E">(</span><span style="color:#032F62">"Error 2"</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E">} </span><span style="color:#D73A49">catch</span><span style="color:#24292E"> (</span><span style="color:#005CC5">Exception</span><span style="color:#24292E"> $e) {</span></span> +<span class="line"><span style="color:#005CC5"> echo</span><span style="color:#24292E"> $e</span><span style="color:#D73A49">-></span><span style="color:#6F42C1">getMessage</span><span style="color:#24292E">() </span><span style="color:#D73A49">.</span><span style="color:#005CC5"> PHP_EOL</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#6A737D"> // => Error 2</span></span> +<span class="line"><span style="color:#005CC5"> echo</span><span style="color:#24292E"> $e</span><span style="color:#D73A49">-></span><span style="color:#6F42C1">getPrevious</span><span style="color:#24292E">()</span><span style="color:#D73A49">-></span><span style="color:#6F42C1">getMessage</span><span style="color:#24292E">() </span><span style="color:#D73A49">.</span><span style="color:#005CC5"> PHP_EOL</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#6A737D"> // => Error 1</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> この知識を元に、トークンの出力部を解析してみる。 @@ -273,15 +276,17 @@ 出力部をコメントや改行を追加して再掲する: </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> -<span class="hljs-keyword">try</span> { - <span class="hljs-title function_ invoke__">f</span>(<span class="hljs-title function_ invoke__">g</span>() / <span class="hljs-keyword">__LINE__</span>); -} <span class="hljs-keyword">catch</span> (<span class="hljs-built_in">Throwable</span> <span class="hljs-variable">$e</span>) { - <span class="hljs-keyword">while</span> (<span class="hljs-variable">$e</span> = <span class="hljs-variable">$e</span>-><span class="hljs-title function_ invoke__">getPrevious</span>()) { - <span class="hljs-title function_ invoke__">printf</span>(<span class="hljs-string">'%c'</span>, <span class="hljs-variable">$e</span>-><span class="hljs-title function_ invoke__">getLine</span>() + <span class="hljs-number">23</span>); - } - <span class="hljs-keyword">echo</span> <span class="hljs-string">"\n"</span>; -}</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> +<span class="line"><span style="color:#D73A49">try</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#6F42C1"> f</span><span style="color:#24292E">(</span><span style="color:#6F42C1">g</span><span style="color:#24292E">() </span><span style="color:#D73A49">/</span><span style="color:#005CC5"> __LINE__</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E">} </span><span style="color:#D73A49">catch</span><span style="color:#24292E"> (</span><span style="color:#005CC5">Throwable</span><span style="color:#24292E"> $e) {</span></span> +<span class="line"><span style="color:#D73A49"> while</span><span style="color:#24292E"> ($e </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $e</span><span style="color:#D73A49">-></span><span style="color:#6F42C1">getPrevious</span><span style="color:#24292E">()) {</span></span> +<span class="line"><span style="color:#005CC5"> printf</span><span style="color:#24292E">(</span><span style="color:#032F62">'%c'</span><span style="color:#24292E">, $e</span><span style="color:#D73A49">-></span><span style="color:#6F42C1">getLine</span><span style="color:#24292E">() </span><span style="color:#D73A49">+</span><span style="color:#005CC5"> 23</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#005CC5"> echo</span><span style="color:#032F62"> "</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> 出力をおこなう <code>catch</code> 節を見てみると、 <code>Throwable::getPrevious()</code> を呼び出してエラーチェインを辿り、 <code>Throwable::getLine()</code> でエラーが発生した行数を取得している。その行数に <code>23</code> なるマジックナンバーを足し、フォーマット指定子 <code>%c</code> で出力している。 @@ -291,7 +296,9 @@ フォーマット指定子 <code>%c</code> は、整数を ASCII コード<span></span> と見做して印字する。トークン <code>#base64_decode('SGVsbG8sIFdvcmxkIQ==')</code> の <code>b</code> であれば、ASCII コード <code>98</code> なので、75 行目で発生したエラー、 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-number">1</span>, <span class="hljs-number">20</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>,</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#005CC5">1</span><span style="color:#24292E">, </span><span style="color:#005CC5">20</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span></code></pre> + </div> <p> によって表現されている。エラーを起こす方法はいろいろと考えられるが、今回はゼロ除算を使った。 @@ -308,38 +315,44 @@ <code>f()</code> の定義を再掲する (エラーオブジェクトの行数を利用しているので、一部分だけ抜き出すと値が変わることに注意): </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">f</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> <span class="hljs-variable">$i</span></span>) </span>{ - <span class="hljs-keyword">if</span> (<span class="hljs-variable">$i</span> < <span class="hljs-number">0</span>) <span class="hljs-title function_ invoke__">f</span>(); - <span class="hljs-keyword">try</span> { - <span class="hljs-keyword">match</span> (<span class="hljs-variable">$i</span>) { - <span class="hljs-number">0</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, <span class="hljs-comment">// 12 行目</span> - - - - <span class="hljs-number">15</span>, <span class="hljs-number">36</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - <span class="hljs-number">14</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - <span class="hljs-number">37</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, - - <span class="hljs-comment">// (略)</span> - - <span class="hljs-number">30</span> => <span class="hljs-number">0</span> / <span class="hljs-number">0</span>, <span class="hljs-comment">// 97 行目</span> - }; - } <span class="hljs-keyword">finally</span> { - <span class="hljs-title function_ invoke__">f</span>(<span class="hljs-variable">$i</span> - <span class="hljs-number">1</span>); - } -}</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">function</span><span style="color:#6F42C1"> f</span><span style="color:#24292E">(</span><span style="color:#D73A49">int</span><span style="color:#24292E"> $i) {</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> ($i </span><span style="color:#D73A49"><</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">) </span><span style="color:#6F42C1">f</span><span style="color:#24292E">();</span></span> +<span class="line"><span style="color:#D73A49"> try</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> match</span><span style="color:#24292E"> ($i) {</span></span> +<span class="line"><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">, </span><span style="color:#6A737D">// 12 行目</span></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5"> 15</span><span style="color:#24292E">, </span><span style="color:#005CC5">36</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#005CC5"> 14</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#005CC5"> 37</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6A737D"> // (略)</span></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5"> 30</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> /</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">, </span><span style="color:#6A737D">// 97 行目</span></span> +<span class="line"><span style="color:#24292E"> };</span></span> +<span class="line"><span style="color:#24292E"> } </span><span style="color:#D73A49">finally</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#6F42C1"> f</span><span style="color:#24292E">($i </span><span style="color:#D73A49">-</span><span style="color:#005CC5"> 1</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> 前述のように、 <code>finally</code> 節でエラーを投げると PHP 処理系が <code>$previous</code> を設定する。ここでは、エラーを繋げるために <code>f()</code> を再帰呼び出ししている。最初に <code>f()</code> を呼び出している箇所を確認すると、 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> -<span class="hljs-keyword">try</span> { - <span class="hljs-title function_ invoke__">f</span>(<span class="hljs-title function_ invoke__">g</span>() / <span class="hljs-keyword">__LINE__</span>); <span class="hljs-comment">// 3 行目</span></code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> +<span class="line"><span style="color:#D73A49">try</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#6F42C1"> f</span><span style="color:#24292E">(</span><span style="color:#6F42C1">g</span><span style="color:#24292E">() </span><span style="color:#D73A49">/</span><span style="color:#005CC5"> __LINE__</span><span style="color:#24292E">); </span><span style="color:#6A737D">// 3 行目</span></span></code></pre> + </div> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">g</span>(<span class="hljs-params"></span>) </span>{ - <span class="hljs-keyword">return</span> <span class="hljs-keyword">__LINE__</span>; <span class="hljs-comment">// 111 行目</span> -}</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">function</span><span style="color:#6F42C1"> g</span><span style="color:#24292E">() {</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#005CC5"> __LINE__</span><span style="color:#24292E">; </span><span style="color:#6A737D">// 111 行目</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> <code>f()</code> には <code>111 / 3</code> で <code>37</code> が渡されることがわかる。そこから 1 ずつ減らして再帰呼び出ししていき、0 より小さくなったら <code>f()</code> を引数なしで呼び出す。引数の数が足りないと呼び出しに失敗するので、再帰はここで止まる。 diff --git a/vhosts/blog/public/posts/2023-03-10/rewrite-this-blog-generator/index.html b/vhosts/blog/public/posts/2023-03-10/rewrite-this-blog-generator/index.html index 883b3ce5..f3eb6ae2 100644 --- a/vhosts/blog/public/posts/2023-03-10/rewrite-this-blog-generator/index.html +++ b/vhosts/blog/public/posts/2023-03-10/rewrite-this-blog-generator/index.html @@ -13,8 +13,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>このブログのジェネレータを書き直した|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> diff --git a/vhosts/blog/public/posts/2023-04-01/implementation-of-minimal-png-image-encoder/index.html b/vhosts/blog/public/posts/2023-04-01/implementation-of-minimal-png-image-encoder/index.html index 4255b561..11831bdf 100644 --- a/vhosts/blog/public/posts/2023-04-01/implementation-of-minimal-png-image-encoder/index.html +++ b/vhosts/blog/public/posts/2023-04-01/implementation-of-minimal-png-image-encoder/index.html @@ -13,8 +13,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>PNG 画像の最小構成エンコーダを実装する|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -98,44 +97,46 @@ 以下のソースコードをベースにする。今回 PNG のデコーダは扱わないので、読み込みには Go の標準ライブラリ <code>image/png</code> を用いる。 </p> - <pre class="highlight" language="go"><code class="highlight"><span class="hljs-keyword">package</span> main - -<span class="hljs-keyword">import</span> ( - <span class="hljs-string">"image"</span> - _ <span class="hljs-string">"image/png"</span> - <span class="hljs-string">"io"</span> - <span class="hljs-string">"os"</span> -) - -<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> { - inFile, err := os.Open(<span class="hljs-string">"input.png"</span>) - <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> { - <span class="hljs-built_in">panic</span>(err) - } - <span class="hljs-keyword">defer</span> inFile.Close() - - img, _, err := image.Decode(inFile) - <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> { - <span class="hljs-built_in">panic</span>(err) - } - - outFile, err := os.Create(<span class="hljs-string">"output.png"</span>) - <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> { - <span class="hljs-built_in">panic</span>(err) - } - <span class="hljs-keyword">defer</span> outFile.Close() - - writePng(outFile, img) -} - -<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">writePng</span><span class="hljs-params">(w io.Writer, img image.Image)</span></span> { - width := <span class="hljs-type">uint32</span>(img.Bounds().Dx()) - height := <span class="hljs-type">uint32</span>(img.Bounds().Dy()) - writeSignature(w) - writeChunkIhdr(w, width, height) - writeChunkIdat(w, width, height, img) - writeChunkIend(w) -}</code></pre> + <div class="codeblock" language="go"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">package</span><span style="color:#6F42C1"> main</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">import</span><span style="color:#24292E"> (</span></span> +<span class="line"><span style="color:#032F62"> "</span><span style="color:#6F42C1">image</span><span style="color:#032F62">"</span></span> +<span class="line"><span style="color:#24292E"> _ </span><span style="color:#032F62">"</span><span style="color:#6F42C1">image/png</span><span style="color:#032F62">"</span></span> +<span class="line"><span style="color:#032F62"> "</span><span style="color:#6F42C1">io</span><span style="color:#032F62">"</span></span> +<span class="line"><span style="color:#032F62"> "</span><span style="color:#6F42C1">os</span><span style="color:#032F62">"</span></span> +<span class="line"><span style="color:#24292E">)</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> main</span><span style="color:#24292E">() {</span></span> +<span class="line"><span style="color:#24292E"> inFile, err </span><span style="color:#D73A49">:=</span><span style="color:#24292E"> os.</span><span style="color:#6F42C1">Open</span><span style="color:#24292E">(</span><span style="color:#032F62">"input.png"</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> err </span><span style="color:#D73A49">!=</span><span style="color:#005CC5"> nil</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#6F42C1"> panic</span><span style="color:#24292E">(err)</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#D73A49"> defer</span><span style="color:#24292E"> inFile.</span><span style="color:#6F42C1">Close</span><span style="color:#24292E">()</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E"> img, _, err </span><span style="color:#D73A49">:=</span><span style="color:#24292E"> image.</span><span style="color:#6F42C1">Decode</span><span style="color:#24292E">(inFile)</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> err </span><span style="color:#D73A49">!=</span><span style="color:#005CC5"> nil</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#6F42C1"> panic</span><span style="color:#24292E">(err)</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E"> outFile, err </span><span style="color:#D73A49">:=</span><span style="color:#24292E"> os.</span><span style="color:#6F42C1">Create</span><span style="color:#24292E">(</span><span style="color:#032F62">"output.png"</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> err </span><span style="color:#D73A49">!=</span><span style="color:#005CC5"> nil</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#6F42C1"> panic</span><span style="color:#24292E">(err)</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#D73A49"> defer</span><span style="color:#24292E"> outFile.</span><span style="color:#6F42C1">Close</span><span style="color:#24292E">()</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6F42C1"> writePng</span><span style="color:#24292E">(outFile, img)</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> writePng</span><span style="color:#24292E">(</span><span style="color:#E36209">w</span><span style="color:#6F42C1"> io</span><span style="color:#24292E">.</span><span style="color:#6F42C1">Writer</span><span style="color:#24292E">, </span><span style="color:#E36209">img</span><span style="color:#6F42C1"> image</span><span style="color:#24292E">.</span><span style="color:#6F42C1">Image</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#24292E"> width </span><span style="color:#D73A49">:=</span><span style="color:#D73A49"> uint32</span><span style="color:#24292E">(img.</span><span style="color:#6F42C1">Bounds</span><span style="color:#24292E">().</span><span style="color:#6F42C1">Dx</span><span style="color:#24292E">())</span></span> +<span class="line"><span style="color:#24292E"> height </span><span style="color:#D73A49">:=</span><span style="color:#D73A49"> uint32</span><span style="color:#24292E">(img.</span><span style="color:#6F42C1">Bounds</span><span style="color:#24292E">().</span><span style="color:#6F42C1">Dy</span><span style="color:#24292E">())</span></span> +<span class="line"><span style="color:#6F42C1"> writeSignature</span><span style="color:#24292E">(w)</span></span> +<span class="line"><span style="color:#6F42C1"> writeChunkIhdr</span><span style="color:#24292E">(w, width, height)</span></span> +<span class="line"><span style="color:#6F42C1"> writeChunkIdat</span><span style="color:#24292E">(w, width, height, img)</span></span> +<span class="line"><span style="color:#6F42C1"> writeChunkIend</span><span style="color:#24292E">(w)</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> 以降は、<code>writeSignature</code> や <code>writeChunkIhdr</code> などを実装していく。 @@ -189,21 +190,23 @@ <code>writeSignature</code> の実装はこちら: </p> - <pre class="highlight" language="go"><code class="highlight"><span class="hljs-keyword">import</span> <span class="hljs-string">"encoding/binary"</span> - -<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">writeSignature</span><span class="hljs-params">(w io.Writer)</span></span> { - sig := [<span class="hljs-number">8</span>]<span class="hljs-type">uint8</span>{ - <span class="hljs-number">0x89</span>, - <span class="hljs-number">0x50</span>, <span class="hljs-comment">// P</span> - <span class="hljs-number">0x4E</span>, <span class="hljs-comment">// N</span> - <span class="hljs-number">0x47</span>, <span class="hljs-comment">// G</span> - <span class="hljs-number">0x0D</span>, <span class="hljs-comment">// CR</span> - <span class="hljs-number">0x0A</span>, <span class="hljs-comment">// LF</span> - <span class="hljs-number">0x1A</span>, <span class="hljs-comment">// EOF (^Z)</span> - <span class="hljs-number">0x0A</span>, <span class="hljs-comment">// LF</span> - } - binary.Write(w, binary.BigEndian, sig) -}</code></pre> + <div class="codeblock" language="go"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">import</span><span style="color:#032F62"> "</span><span style="color:#6F42C1">encoding/binary</span><span style="color:#032F62">"</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> writeSignature</span><span style="color:#24292E">(</span><span style="color:#E36209">w</span><span style="color:#6F42C1"> io</span><span style="color:#24292E">.</span><span style="color:#6F42C1">Writer</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#24292E"> sig </span><span style="color:#D73A49">:=</span><span style="color:#24292E"> [</span><span style="color:#005CC5">8</span><span style="color:#24292E">]</span><span style="color:#D73A49">uint8</span><span style="color:#24292E">{</span></span> +<span class="line"><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">89</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">50</span><span style="color:#24292E">, </span><span style="color:#6A737D">// P</span></span> +<span class="line"><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">4E</span><span style="color:#24292E">, </span><span style="color:#6A737D">// N</span></span> +<span class="line"><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">47</span><span style="color:#24292E">, </span><span style="color:#6A737D">// G</span></span> +<span class="line"><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">0D</span><span style="color:#24292E">, </span><span style="color:#6A737D">// CR</span></span> +<span class="line"><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">0A</span><span style="color:#24292E">, </span><span style="color:#6A737D">// LF</span></span> +<span class="line"><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">1A</span><span style="color:#24292E">, </span><span style="color:#6A737D">// EOF (^Z)</span></span> +<span class="line"><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">0A</span><span style="color:#24292E">, </span><span style="color:#6A737D">// LF</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(w, binary.BigEndian, sig)</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> <code>encoding/binary</code> パッケージの <code>binary.Write</code> を使い、固定の 8 バイトを書き込む。 @@ -238,55 +241,59 @@ CRC (Cyclic Redundancy Check) は誤り検出符号の一種。Go 言語では <code>hash/crc32</code> パッケージにあるが、今回はこれも自前で実装する。PNG の仕様書に C 言語のサンプルコードが載っている (<a href="https://www.w3.org/TR/png/#D-CRCAppendix" rel="noreferrer" target="_blank">D. Sample CRC implementation</a>) ので、これを Go に移植する。 </p> - <pre class="highlight" language="go"><code class="highlight"><span class="hljs-keyword">var</span> ( - crcTable [<span class="hljs-number">256</span>]<span class="hljs-type">uint32</span> - crcTableComputed <span class="hljs-type">bool</span> -) - -<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">makeCrcTable</span><span class="hljs-params">()</span></span> { - <span class="hljs-keyword">for</span> n := <span class="hljs-number">0</span>; n < <span class="hljs-number">256</span>; n++ { - c := <span class="hljs-type">uint32</span>(n) - <span class="hljs-keyword">for</span> k := <span class="hljs-number">0</span>; k < <span class="hljs-number">8</span>; k++ { - <span class="hljs-keyword">if</span> (c & <span class="hljs-number">1</span>) != <span class="hljs-number">0</span> { - c = <span class="hljs-number">0xEDB88320</span> ^ (c >> <span class="hljs-number">1</span>) - } <span class="hljs-keyword">else</span> { - c = c >> <span class="hljs-number">1</span> - } - } - crcTable[n] = c - } - crcTableComputed = <span class="hljs-literal">true</span> -} - -<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">updateCrc</span><span class="hljs-params">(crc <span class="hljs-type">uint32</span>, buf []<span class="hljs-type">byte</span>)</span></span> <span class="hljs-type">uint32</span> { - <span class="hljs-keyword">if</span> !crcTableComputed { - makeCrcTable() - } - - c := crc - <span class="hljs-keyword">for</span> n := <span class="hljs-number">0</span>; n < <span class="hljs-built_in">len</span>(buf); n++ { - c = crcTable[(c^<span class="hljs-type">uint32</span>(buf[n]))&<span class="hljs-number">0xFF</span>] ^ (c >> <span class="hljs-number">8</span>) - } - <span class="hljs-keyword">return</span> c -} - -<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">crc</span><span class="hljs-params">(buf []<span class="hljs-type">byte</span>)</span></span> <span class="hljs-type">uint32</span> { - <span class="hljs-keyword">return</span> updateCrc(<span class="hljs-number">0xFFFFFFFF</span>, buf) ^ <span class="hljs-number">0xFFFFFFFF</span> -}</code></pre> + <div class="codeblock" language="go"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">var</span><span style="color:#24292E"> (</span></span> +<span class="line"><span style="color:#24292E"> crcTable [</span><span style="color:#005CC5">256</span><span style="color:#24292E">]</span><span style="color:#D73A49">uint32</span></span> +<span class="line"><span style="color:#24292E"> crcTableComputed </span><span style="color:#D73A49">bool</span></span> +<span class="line"><span style="color:#24292E">)</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> makeCrcTable</span><span style="color:#24292E">() {</span></span> +<span class="line"><span style="color:#D73A49"> for</span><span style="color:#24292E"> n </span><span style="color:#D73A49">:=</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">; n </span><span style="color:#D73A49"><</span><span style="color:#005CC5"> 256</span><span style="color:#24292E">; n</span><span style="color:#D73A49">++</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> c </span><span style="color:#D73A49">:=</span><span style="color:#D73A49"> uint32</span><span style="color:#24292E">(n)</span></span> +<span class="line"><span style="color:#D73A49"> for</span><span style="color:#24292E"> k </span><span style="color:#D73A49">:=</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">; k </span><span style="color:#D73A49"><</span><span style="color:#005CC5"> 8</span><span style="color:#24292E">; k</span><span style="color:#D73A49">++</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> (c </span><span style="color:#D73A49">&</span><span style="color:#005CC5"> 1</span><span style="color:#24292E">) </span><span style="color:#D73A49">!=</span><span style="color:#005CC5"> 0</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> c </span><span style="color:#D73A49">=</span><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">EDB88320</span><span style="color:#D73A49"> ^</span><span style="color:#24292E"> (c </span><span style="color:#D73A49">>></span><span style="color:#005CC5"> 1</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#24292E"> } </span><span style="color:#D73A49">else</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> c </span><span style="color:#D73A49">=</span><span style="color:#24292E"> c </span><span style="color:#D73A49">>></span><span style="color:#005CC5"> 1</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E"> crcTable[n] </span><span style="color:#D73A49">=</span><span style="color:#24292E"> c</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E"> crcTableComputed </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> true</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> updateCrc</span><span style="color:#24292E">(</span><span style="color:#E36209">crc</span><span style="color:#D73A49"> uint32</span><span style="color:#24292E">, </span><span style="color:#E36209">buf</span><span style="color:#24292E"> []</span><span style="color:#D73A49">byte</span><span style="color:#24292E">) </span><span style="color:#D73A49">uint32</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#D73A49"> !</span><span style="color:#24292E">crcTableComputed {</span></span> +<span class="line"><span style="color:#6F42C1"> makeCrcTable</span><span style="color:#24292E">()</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E"> c </span><span style="color:#D73A49">:=</span><span style="color:#24292E"> crc</span></span> +<span class="line"><span style="color:#D73A49"> for</span><span style="color:#24292E"> n </span><span style="color:#D73A49">:=</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">; n </span><span style="color:#D73A49"><</span><span style="color:#6F42C1"> len</span><span style="color:#24292E">(buf); n</span><span style="color:#D73A49">++</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> c </span><span style="color:#D73A49">=</span><span style="color:#24292E"> crcTable[(c</span><span style="color:#D73A49">^uint32</span><span style="color:#24292E">(buf[n]))</span><span style="color:#D73A49">&0x</span><span style="color:#005CC5">FF</span><span style="color:#24292E">] </span><span style="color:#D73A49">^</span><span style="color:#24292E"> (c </span><span style="color:#D73A49">>></span><span style="color:#005CC5"> 8</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#24292E"> c</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> crc</span><span style="color:#24292E">(</span><span style="color:#E36209">buf</span><span style="color:#24292E"> []</span><span style="color:#D73A49">byte</span><span style="color:#24292E">) </span><span style="color:#D73A49">uint32</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#6F42C1"> updateCrc</span><span style="color:#24292E">(</span><span style="color:#D73A49">0x</span><span style="color:#005CC5">FFFFFFFF</span><span style="color:#24292E">, buf) </span><span style="color:#D73A49">^</span><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">FFFFFFFF</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> できた <code>crc</code> 関数を使って、chunk 一般を書き込む関数も用意しておこう。 </p> - <pre class="highlight" language="go"><code class="highlight"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">writeChunk</span><span class="hljs-params">(w io.Writer, chunkType <span class="hljs-type">string</span>, data []<span class="hljs-type">byte</span>)</span></span> { - typeAndData := <span class="hljs-built_in">make</span>([]<span class="hljs-type">byte</span>, <span class="hljs-number">0</span>, <span class="hljs-built_in">len</span>(chunkType)+<span class="hljs-built_in">len</span>(data)) - typeAndData = <span class="hljs-built_in">append</span>(typeAndData, []<span class="hljs-type">byte</span>(chunkType)...) - typeAndData = <span class="hljs-built_in">append</span>(typeAndData, data...) - - binary.Write(w, binary.BigEndian, <span class="hljs-type">uint32</span>(<span class="hljs-built_in">len</span>(data))) - binary.Write(w, binary.BigEndian, typeAndData) - binary.Write(w, binary.BigEndian, crc(typeAndData)) -}</code></pre> + <div class="codeblock" language="go"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> writeChunk</span><span style="color:#24292E">(</span><span style="color:#E36209">w</span><span style="color:#6F42C1"> io</span><span style="color:#24292E">.</span><span style="color:#6F42C1">Writer</span><span style="color:#24292E">, </span><span style="color:#E36209">chunkType</span><span style="color:#D73A49"> string</span><span style="color:#24292E">, </span><span style="color:#E36209">data</span><span style="color:#24292E"> []</span><span style="color:#D73A49">byte</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#24292E"> typeAndData </span><span style="color:#D73A49">:=</span><span style="color:#6F42C1"> make</span><span style="color:#24292E">([]</span><span style="color:#D73A49">byte</span><span style="color:#24292E">, </span><span style="color:#005CC5">0</span><span style="color:#24292E">, </span><span style="color:#6F42C1">len</span><span style="color:#24292E">(chunkType)</span><span style="color:#D73A49">+</span><span style="color:#6F42C1">len</span><span style="color:#24292E">(data))</span></span> +<span class="line"><span style="color:#24292E"> typeAndData </span><span style="color:#D73A49">=</span><span style="color:#6F42C1"> append</span><span style="color:#24292E">(typeAndData, []</span><span style="color:#D73A49">byte</span><span style="color:#24292E">(chunkType)</span><span style="color:#D73A49">...</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#24292E"> typeAndData </span><span style="color:#D73A49">=</span><span style="color:#6F42C1"> append</span><span style="color:#24292E">(typeAndData, data</span><span style="color:#D73A49">...</span><span style="color:#24292E">)</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(w, binary.BigEndian, </span><span style="color:#D73A49">uint32</span><span style="color:#24292E">(</span><span style="color:#6F42C1">len</span><span style="color:#24292E">(data)))</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(w, binary.BigEndian, typeAndData)</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(w, binary.BigEndian, </span><span style="color:#6F42C1">crc</span><span style="color:#24292E">(typeAndData))</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> 仕様どおり、<code>chunkType</code> と <code>data</code> から CRC を計算し、<code>data</code> の長さと合わせて書き込んでいる。PNG では基本的に big endian を使うことに注意する。 @@ -372,20 +379,22 @@ 今回ほとんどのデータは決め打ちするので、データに応じて変わるのは width と height だけになる。コードは次のようになる。 </p> - <pre class="highlight" language="go"><code class="highlight"><span class="hljs-keyword">import</span> <span class="hljs-string">"bytes"</span> - -<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">writeChunkIhdr</span><span class="hljs-params">(w io.Writer, width, height <span class="hljs-type">uint32</span>)</span></span> { - <span class="hljs-keyword">var</span> buf bytes.Buffer - binary.Write(&buf, binary.BigEndian, width) - binary.Write(&buf, binary.BigEndian, height) - binary.Write(&buf, binary.BigEndian, <span class="hljs-type">uint8</span>(<span class="hljs-number">8</span>)) - binary.Write(&buf, binary.BigEndian, <span class="hljs-type">uint8</span>(<span class="hljs-number">2</span>)) - binary.Write(&buf, binary.BigEndian, <span class="hljs-type">uint8</span>(<span class="hljs-number">0</span>)) - binary.Write(&buf, binary.BigEndian, <span class="hljs-type">uint8</span>(<span class="hljs-number">0</span>)) - binary.Write(&buf, binary.BigEndian, <span class="hljs-type">uint8</span>(<span class="hljs-number">0</span>)) - - writeChunk(w, <span class="hljs-string">"IHDR"</span>, buf.Bytes()) -}</code></pre> + <div class="codeblock" language="go"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">import</span><span style="color:#032F62"> "</span><span style="color:#6F42C1">bytes</span><span style="color:#032F62">"</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> writeChunkIhdr</span><span style="color:#24292E">(</span><span style="color:#E36209">w</span><span style="color:#6F42C1"> io</span><span style="color:#24292E">.</span><span style="color:#6F42C1">Writer</span><span style="color:#24292E">, </span><span style="color:#E36209">width</span><span style="color:#24292E">, </span><span style="color:#E36209">height</span><span style="color:#D73A49"> uint32</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#D73A49"> var</span><span style="color:#24292E"> buf </span><span style="color:#6F42C1">bytes</span><span style="color:#24292E">.</span><span style="color:#6F42C1">Buffer</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.BigEndian, width)</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.BigEndian, height)</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.BigEndian, </span><span style="color:#D73A49">uint8</span><span style="color:#24292E">(</span><span style="color:#005CC5">8</span><span style="color:#24292E">))</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.BigEndian, </span><span style="color:#D73A49">uint8</span><span style="color:#24292E">(</span><span style="color:#005CC5">2</span><span style="color:#24292E">))</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.BigEndian, </span><span style="color:#D73A49">uint8</span><span style="color:#24292E">(</span><span style="color:#005CC5">0</span><span style="color:#24292E">))</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.BigEndian, </span><span style="color:#D73A49">uint8</span><span style="color:#24292E">(</span><span style="color:#005CC5">0</span><span style="color:#24292E">))</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.BigEndian, </span><span style="color:#D73A49">uint8</span><span style="color:#24292E">(</span><span style="color:#005CC5">0</span><span style="color:#24292E">))</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6F42C1"> writeChunk</span><span style="color:#24292E">(w, </span><span style="color:#032F62">"IHDR"</span><span style="color:#24292E">, buf.</span><span style="color:#6F42C1">Bytes</span><span style="color:#24292E">())</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> </section> <section id="section--implement-png-encoder--idat-chunk"> @@ -426,22 +435,24 @@ Adler-32 も CRC と同じく誤り検出符号である。こちらも zlib の仕様書に C 言語でサンプルコードが記載されている (<a href="https://www.rfc-editor.org/rfc/rfc1950#section-9" rel="noreferrer" target="_blank">9. Appendix: Sample code</a>) ので、Go に移植する。 </p> - <pre class="highlight" language="go"><code class="highlight"><span class="hljs-keyword">const</span> adler32Base = <span class="hljs-number">65521</span> - -<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">updateAdler32</span><span class="hljs-params">(adler <span class="hljs-type">uint32</span>, buf []<span class="hljs-type">byte</span>)</span></span> <span class="hljs-type">uint32</span> { - s1 := adler & <span class="hljs-number">0xFFFF</span> - s2 := (adler >> <span class="hljs-number">16</span>) & <span class="hljs-number">0xFFFF</span> - - <span class="hljs-keyword">for</span> n := <span class="hljs-number">0</span>; n < <span class="hljs-built_in">len</span>(buf); n++ { - s1 = (s1 + <span class="hljs-type">uint32</span>(buf[n])) % adler32Base - s2 = (s2 + s1) % adler32Base - } - <span class="hljs-keyword">return</span> (s2 << <span class="hljs-number">16</span>) + s1 -} - -<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">adler32</span><span class="hljs-params">(buf []<span class="hljs-type">byte</span>)</span></span> <span class="hljs-type">uint32</span> { - <span class="hljs-keyword">return</span> updateAdler32(<span class="hljs-number">1</span>, buf) -}</code></pre> + <div class="codeblock" language="go"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">const</span><span style="color:#005CC5"> adler32Base</span><span style="color:#D73A49"> =</span><span style="color:#005CC5"> 65521</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> updateAdler32</span><span style="color:#24292E">(</span><span style="color:#E36209">adler</span><span style="color:#D73A49"> uint32</span><span style="color:#24292E">, </span><span style="color:#E36209">buf</span><span style="color:#24292E"> []</span><span style="color:#D73A49">byte</span><span style="color:#24292E">) </span><span style="color:#D73A49">uint32</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> s1 </span><span style="color:#D73A49">:=</span><span style="color:#24292E"> adler </span><span style="color:#D73A49">&</span><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">FFFF</span></span> +<span class="line"><span style="color:#24292E"> s2 </span><span style="color:#D73A49">:=</span><span style="color:#24292E"> (adler </span><span style="color:#D73A49">>></span><span style="color:#005CC5"> 16</span><span style="color:#24292E">) </span><span style="color:#D73A49">&</span><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">FFFF</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49"> for</span><span style="color:#24292E"> n </span><span style="color:#D73A49">:=</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">; n </span><span style="color:#D73A49"><</span><span style="color:#6F42C1"> len</span><span style="color:#24292E">(buf); n</span><span style="color:#D73A49">++</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> s1 </span><span style="color:#D73A49">=</span><span style="color:#24292E"> (s1 </span><span style="color:#D73A49">+</span><span style="color:#D73A49"> uint32</span><span style="color:#24292E">(buf[n])) </span><span style="color:#D73A49">%</span><span style="color:#24292E"> adler32Base</span></span> +<span class="line"><span style="color:#24292E"> s2 </span><span style="color:#D73A49">=</span><span style="color:#24292E"> (s2 </span><span style="color:#D73A49">+</span><span style="color:#24292E"> s1) </span><span style="color:#D73A49">%</span><span style="color:#24292E"> adler32Base</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#24292E"> (s2 </span><span style="color:#D73A49"><<</span><span style="color:#005CC5"> 16</span><span style="color:#24292E">) </span><span style="color:#D73A49">+</span><span style="color:#24292E"> s1</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> adler32</span><span style="color:#24292E">(</span><span style="color:#E36209">buf</span><span style="color:#24292E"> []</span><span style="color:#D73A49">byte</span><span style="color:#24292E">) </span><span style="color:#D73A49">uint32</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#6F42C1"> updateAdler32</span><span style="color:#24292E">(</span><span style="color:#005CC5">1</span><span style="color:#24292E">, buf)</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> 「データ」の部分には圧縮したデータが入るのだが、真面目に deflate アルゴリズムを実装する必要はない。Zlib には無圧縮のデータブロックを格納することができるので、これを使う。本来は、データの圧縮効率の悪いランダムなデータをそのまま格納するためのものだが、今回は deflate の実装をサボるために使う。 @@ -473,30 +484,32 @@ 実際にこの手抜き zlib を実装したものがこちら: </p> - <pre class="highlight" language="go"><code class="highlight"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">encodeZlib</span><span class="hljs-params">(data []<span class="hljs-type">byte</span>)</span></span> []<span class="hljs-type">byte</span> { - <span class="hljs-keyword">var</span> buf bytes.Buffer - - binary.Write(&buf, binary.BigEndian, <span class="hljs-type">uint8</span>(<span class="hljs-number">0x78</span>)) - binary.Write(&buf, binary.BigEndian, <span class="hljs-type">uint8</span>(<span class="hljs-number">0x01</span>)) - blockSize := <span class="hljs-number">65535</span> - isFinalBlock := <span class="hljs-literal">false</span> - <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; !isFinalBlock; i++ { - <span class="hljs-keyword">var</span> block []<span class="hljs-type">byte</span> - <span class="hljs-keyword">if</span> <span class="hljs-built_in">len</span>(data) <= (i+<span class="hljs-number">1</span>)*blockSize { - block = data[i*blockSize:] - isFinalBlock = <span class="hljs-literal">true</span> - } <span class="hljs-keyword">else</span> { - block = data[i*blockSize : (i+<span class="hljs-number">1</span>)*blockSize] - } - binary.Write(&buf, binary.BigEndian, isFinalBlock) - binary.Write(&buf, binary.LittleEndian, <span class="hljs-type">uint16</span>(<span class="hljs-built_in">len</span>(block))) - binary.Write(&buf, binary.LittleEndian, <span class="hljs-type">uint16</span>(^<span class="hljs-built_in">len</span>(block))) - binary.Write(&buf, binary.LittleEndian, block) - } - binary.Write(&buf, binary.BigEndian, adler32(data)) - - <span class="hljs-keyword">return</span> buf.Bytes() -}</code></pre> + <div class="codeblock" language="go"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> encodeZlib</span><span style="color:#24292E">(</span><span style="color:#E36209">data</span><span style="color:#24292E"> []</span><span style="color:#D73A49">byte</span><span style="color:#24292E">) []</span><span style="color:#D73A49">byte</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> var</span><span style="color:#24292E"> buf </span><span style="color:#6F42C1">bytes</span><span style="color:#24292E">.</span><span style="color:#6F42C1">Buffer</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.BigEndian, </span><span style="color:#D73A49">uint8</span><span style="color:#24292E">(</span><span style="color:#D73A49">0x</span><span style="color:#005CC5">78</span><span style="color:#24292E">))</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.BigEndian, </span><span style="color:#D73A49">uint8</span><span style="color:#24292E">(</span><span style="color:#D73A49">0x</span><span style="color:#005CC5">01</span><span style="color:#24292E">))</span></span> +<span class="line"><span style="color:#24292E"> blockSize </span><span style="color:#D73A49">:=</span><span style="color:#005CC5"> 65535</span></span> +<span class="line"><span style="color:#24292E"> isFinalBlock </span><span style="color:#D73A49">:=</span><span style="color:#005CC5"> false</span></span> +<span class="line"><span style="color:#D73A49"> for</span><span style="color:#24292E"> i </span><span style="color:#D73A49">:=</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">; </span><span style="color:#D73A49">!</span><span style="color:#24292E">isFinalBlock; i</span><span style="color:#D73A49">++</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> var</span><span style="color:#24292E"> block []</span><span style="color:#D73A49">byte</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#6F42C1"> len</span><span style="color:#24292E">(data) </span><span style="color:#D73A49"><=</span><span style="color:#24292E"> (i</span><span style="color:#D73A49">+</span><span style="color:#005CC5">1</span><span style="color:#24292E">)</span><span style="color:#D73A49">*</span><span style="color:#24292E">blockSize {</span></span> +<span class="line"><span style="color:#24292E"> block </span><span style="color:#D73A49">=</span><span style="color:#24292E"> data[i</span><span style="color:#D73A49">*</span><span style="color:#24292E">blockSize:]</span></span> +<span class="line"><span style="color:#24292E"> isFinalBlock </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> true</span></span> +<span class="line"><span style="color:#24292E"> } </span><span style="color:#D73A49">else</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> block </span><span style="color:#D73A49">=</span><span style="color:#24292E"> data[i</span><span style="color:#D73A49">*</span><span style="color:#24292E">blockSize : (i</span><span style="color:#D73A49">+</span><span style="color:#005CC5">1</span><span style="color:#24292E">)</span><span style="color:#D73A49">*</span><span style="color:#24292E">blockSize]</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.BigEndian, isFinalBlock)</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.LittleEndian, </span><span style="color:#D73A49">uint16</span><span style="color:#24292E">(</span><span style="color:#6F42C1">len</span><span style="color:#24292E">(block)))</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.LittleEndian, </span><span style="color:#D73A49">uint16</span><span style="color:#24292E">(</span><span style="color:#D73A49">^</span><span style="color:#6F42C1">len</span><span style="color:#24292E">(block)))</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.LittleEndian, block)</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.BigEndian, </span><span style="color:#6F42C1">adler32</span><span style="color:#24292E">(data))</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#24292E"> buf.</span><span style="color:#6F42C1">Bytes</span><span style="color:#24292E">()</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> </section> <section id="section--implement-png-encoder--idat-chunk--image-data"> @@ -513,20 +526,22 @@ 先ほどの <code>encodeZlib</code> も使って実際に実装したものがこちら: </p> - <pre class="highlight" language="go"><code class="highlight"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">writeChunkIdat</span><span class="hljs-params">(w io.Writer, width, height <span class="hljs-type">uint32</span>, img image.Image)</span></span> { - <span class="hljs-keyword">var</span> pixels bytes.Buffer - <span class="hljs-keyword">for</span> y := <span class="hljs-type">uint32</span>(<span class="hljs-number">0</span>); y < height; y++ { - binary.Write(&pixels, binary.BigEndian, <span class="hljs-type">uint8</span>(<span class="hljs-number">0</span>)) - <span class="hljs-keyword">for</span> x := <span class="hljs-type">uint32</span>(<span class="hljs-number">0</span>); x < width; x++ { - r, g, b, _ := img.At(<span class="hljs-type">int</span>(x), <span class="hljs-type">int</span>(y)).RGBA() - binary.Write(&pixels, binary.BigEndian, <span class="hljs-type">uint8</span>(r)) - binary.Write(&pixels, binary.BigEndian, <span class="hljs-type">uint8</span>(g)) - binary.Write(&pixels, binary.BigEndian, <span class="hljs-type">uint8</span>(b)) - } - } - - writeChunk(w, <span class="hljs-string">"IDAT"</span>, encodeZlib(pixels.Bytes())) -}</code></pre> + <div class="codeblock" language="go"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> writeChunkIdat</span><span style="color:#24292E">(</span><span style="color:#E36209">w</span><span style="color:#6F42C1"> io</span><span style="color:#24292E">.</span><span style="color:#6F42C1">Writer</span><span style="color:#24292E">, </span><span style="color:#E36209">width</span><span style="color:#24292E">, </span><span style="color:#E36209">height</span><span style="color:#D73A49"> uint32</span><span style="color:#24292E">, </span><span style="color:#E36209">img</span><span style="color:#6F42C1"> image</span><span style="color:#24292E">.</span><span style="color:#6F42C1">Image</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#D73A49"> var</span><span style="color:#24292E"> pixels </span><span style="color:#6F42C1">bytes</span><span style="color:#24292E">.</span><span style="color:#6F42C1">Buffer</span></span> +<span class="line"><span style="color:#D73A49"> for</span><span style="color:#24292E"> y </span><span style="color:#D73A49">:=</span><span style="color:#D73A49"> uint32</span><span style="color:#24292E">(</span><span style="color:#005CC5">0</span><span style="color:#24292E">); y </span><span style="color:#D73A49"><</span><span style="color:#24292E"> height; y</span><span style="color:#D73A49">++</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">pixels, binary.BigEndian, </span><span style="color:#D73A49">uint8</span><span style="color:#24292E">(</span><span style="color:#005CC5">0</span><span style="color:#24292E">))</span></span> +<span class="line"><span style="color:#D73A49"> for</span><span style="color:#24292E"> x </span><span style="color:#D73A49">:=</span><span style="color:#D73A49"> uint32</span><span style="color:#24292E">(</span><span style="color:#005CC5">0</span><span style="color:#24292E">); x </span><span style="color:#D73A49"><</span><span style="color:#24292E"> width; x</span><span style="color:#D73A49">++</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> r, g, b, _ </span><span style="color:#D73A49">:=</span><span style="color:#24292E"> img.</span><span style="color:#6F42C1">At</span><span style="color:#24292E">(</span><span style="color:#D73A49">int</span><span style="color:#24292E">(x), </span><span style="color:#D73A49">int</span><span style="color:#24292E">(y)).</span><span style="color:#6F42C1">RGBA</span><span style="color:#24292E">()</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">pixels, binary.BigEndian, </span><span style="color:#D73A49">uint8</span><span style="color:#24292E">(r))</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">pixels, binary.BigEndian, </span><span style="color:#D73A49">uint8</span><span style="color:#24292E">(g))</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">pixels, binary.BigEndian, </span><span style="color:#D73A49">uint8</span><span style="color:#24292E">(b))</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6F42C1"> writeChunk</span><span style="color:#24292E">(w, </span><span style="color:#032F62">"IDAT"</span><span style="color:#24292E">, </span><span style="color:#6F42C1">encodeZlib</span><span style="color:#24292E">(pixels.</span><span style="color:#6F42C1">Bytes</span><span style="color:#24292E">()))</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> </section> </section> @@ -540,9 +555,11 @@ 特に追加のデータはなく、必要なのは chunk type の <code>IEND</code> くらいなので実装は簡単: </p> - <pre class="highlight" language="go"><code class="highlight"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">writeChunkIend</span><span class="hljs-params">(w io.Writer)</span></span> { - writeChunk(w, <span class="hljs-string">"IEND"</span>, <span class="hljs-literal">nil</span>) -}</code></pre> + <div class="codeblock" language="go"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> writeChunkIend</span><span style="color:#24292E">(</span><span style="color:#E36209">w</span><span style="color:#6F42C1"> io</span><span style="color:#24292E">.</span><span style="color:#6F42C1">Writer</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#6F42C1"> writeChunk</span><span style="color:#24292E">(w, </span><span style="color:#032F62">"IEND"</span><span style="color:#24292E">, </span><span style="color:#005CC5">nil</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> </section> </section> @@ -552,180 +569,182 @@ 最後に全ソースコードを再掲しておく。 </p> - <pre class="highlight" language="go"><code class="highlight"><span class="hljs-keyword">package</span> main - -<span class="hljs-keyword">import</span> ( - <span class="hljs-string">"bytes"</span> - <span class="hljs-string">"encoding/binary"</span> - <span class="hljs-string">"image"</span> - _ <span class="hljs-string">"image/png"</span> - <span class="hljs-string">"io"</span> - <span class="hljs-string">"os"</span> -) - -<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> { - inFile, err := os.Open(<span class="hljs-string">"input.png"</span>) - <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> { - <span class="hljs-built_in">panic</span>(err) - } - <span class="hljs-keyword">defer</span> inFile.Close() - - img, _, err := image.Decode(inFile) - <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> { - <span class="hljs-built_in">panic</span>(err) - } - - outFile, err := os.Create(<span class="hljs-string">"output.png"</span>) - <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> { - <span class="hljs-built_in">panic</span>(err) - } - <span class="hljs-keyword">defer</span> outFile.Close() - - writePng(outFile, img) -} - -<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">writePng</span><span class="hljs-params">(w io.Writer, img image.Image)</span></span> { - width := <span class="hljs-type">uint32</span>(img.Bounds().Dx()) - height := <span class="hljs-type">uint32</span>(img.Bounds().Dy()) - writeSignature(w) - writeChunkIhdr(w, width, height) - writeChunkIdat(w, width, height, img) - writeChunkIend(w) -} - -<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">writeSignature</span><span class="hljs-params">(w io.Writer)</span></span> { - sig := [<span class="hljs-number">8</span>]<span class="hljs-type">uint8</span>{ - <span class="hljs-number">0x89</span>, - <span class="hljs-number">0x50</span>, <span class="hljs-comment">// P</span> - <span class="hljs-number">0x4E</span>, <span class="hljs-comment">// N</span> - <span class="hljs-number">0x47</span>, <span class="hljs-comment">// G</span> - <span class="hljs-number">0x0D</span>, <span class="hljs-comment">// CR</span> - <span class="hljs-number">0x0A</span>, <span class="hljs-comment">// LF</span> - <span class="hljs-number">0x1A</span>, <span class="hljs-comment">// EOF (^Z)</span> - <span class="hljs-number">0x0A</span>, <span class="hljs-comment">// LF</span> - } - binary.Write(w, binary.BigEndian, sig) -} - -<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">writeChunkIhdr</span><span class="hljs-params">(w io.Writer, width, height <span class="hljs-type">uint32</span>)</span></span> { - <span class="hljs-keyword">var</span> buf bytes.Buffer - binary.Write(&buf, binary.BigEndian, width) - binary.Write(&buf, binary.BigEndian, height) - binary.Write(&buf, binary.BigEndian, <span class="hljs-type">uint8</span>(<span class="hljs-number">8</span>)) - binary.Write(&buf, binary.BigEndian, <span class="hljs-type">uint8</span>(<span class="hljs-number">2</span>)) - binary.Write(&buf, binary.BigEndian, <span class="hljs-type">uint8</span>(<span class="hljs-number">0</span>)) - binary.Write(&buf, binary.BigEndian, <span class="hljs-type">uint8</span>(<span class="hljs-number">0</span>)) - binary.Write(&buf, binary.BigEndian, <span class="hljs-type">uint8</span>(<span class="hljs-number">0</span>)) - - writeChunk(w, <span class="hljs-string">"IHDR"</span>, buf.Bytes()) -} - -<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">writeChunkIdat</span><span class="hljs-params">(w io.Writer, width, height <span class="hljs-type">uint32</span>, img image.Image)</span></span> { - <span class="hljs-keyword">var</span> pixels bytes.Buffer - <span class="hljs-keyword">for</span> y := <span class="hljs-type">uint32</span>(<span class="hljs-number">0</span>); y < height; y++ { - binary.Write(&pixels, binary.BigEndian, <span class="hljs-type">uint8</span>(<span class="hljs-number">0</span>)) - <span class="hljs-keyword">for</span> x := <span class="hljs-type">uint32</span>(<span class="hljs-number">0</span>); x < width; x++ { - r, g, b, _ := img.At(<span class="hljs-type">int</span>(x), <span class="hljs-type">int</span>(y)).RGBA() - binary.Write(&pixels, binary.BigEndian, <span class="hljs-type">uint8</span>(r)) - binary.Write(&pixels, binary.BigEndian, <span class="hljs-type">uint8</span>(g)) - binary.Write(&pixels, binary.BigEndian, <span class="hljs-type">uint8</span>(b)) - } - } - - writeChunk(w, <span class="hljs-string">"IDAT"</span>, encodeZlib(pixels.Bytes())) -} - -<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">encodeZlib</span><span class="hljs-params">(data []<span class="hljs-type">byte</span>)</span></span> []<span class="hljs-type">byte</span> { - <span class="hljs-keyword">var</span> buf bytes.Buffer - - binary.Write(&buf, binary.BigEndian, <span class="hljs-type">uint8</span>(<span class="hljs-number">0x78</span>)) - binary.Write(&buf, binary.BigEndian, <span class="hljs-type">uint8</span>(<span class="hljs-number">0x01</span>)) - blockSize := <span class="hljs-number">65535</span> - isFinalBlock := <span class="hljs-literal">false</span> - <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; !isFinalBlock; i++ { - <span class="hljs-keyword">var</span> block []<span class="hljs-type">byte</span> - <span class="hljs-keyword">if</span> <span class="hljs-built_in">len</span>(data) <= (i+<span class="hljs-number">1</span>)*blockSize { - block = data[i*blockSize:] - isFinalBlock = <span class="hljs-literal">true</span> - } <span class="hljs-keyword">else</span> { - block = data[i*blockSize : (i+<span class="hljs-number">1</span>)*blockSize] - } - binary.Write(&buf, binary.BigEndian, isFinalBlock) - binary.Write(&buf, binary.LittleEndian, <span class="hljs-type">uint16</span>(<span class="hljs-built_in">len</span>(block))) - binary.Write(&buf, binary.LittleEndian, <span class="hljs-type">uint16</span>(^<span class="hljs-built_in">len</span>(block))) - binary.Write(&buf, binary.LittleEndian, block) - } - binary.Write(&buf, binary.BigEndian, adler32(data)) - - <span class="hljs-keyword">return</span> buf.Bytes() -} - -<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">writeChunkIend</span><span class="hljs-params">(w io.Writer)</span></span> { - writeChunk(w, <span class="hljs-string">"IEND"</span>, <span class="hljs-literal">nil</span>) -} - -<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">writeChunk</span><span class="hljs-params">(w io.Writer, chunkType <span class="hljs-type">string</span>, data []<span class="hljs-type">byte</span>)</span></span> { - typeAndData := <span class="hljs-built_in">make</span>([]<span class="hljs-type">byte</span>, <span class="hljs-number">0</span>, <span class="hljs-built_in">len</span>(chunkType)+<span class="hljs-built_in">len</span>(data)) - typeAndData = <span class="hljs-built_in">append</span>(typeAndData, []<span class="hljs-type">byte</span>(chunkType)...) - typeAndData = <span class="hljs-built_in">append</span>(typeAndData, data...) - - binary.Write(w, binary.BigEndian, <span class="hljs-type">uint32</span>(<span class="hljs-built_in">len</span>(data))) - binary.Write(w, binary.BigEndian, typeAndData) - binary.Write(w, binary.BigEndian, crc(typeAndData)) -} - -<span class="hljs-keyword">var</span> ( - crcTable [<span class="hljs-number">256</span>]<span class="hljs-type">uint32</span> - crcTableComputed <span class="hljs-type">bool</span> -) - -<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">makeCrcTable</span><span class="hljs-params">()</span></span> { - <span class="hljs-keyword">for</span> n := <span class="hljs-number">0</span>; n < <span class="hljs-number">256</span>; n++ { - c := <span class="hljs-type">uint32</span>(n) - <span class="hljs-keyword">for</span> k := <span class="hljs-number">0</span>; k < <span class="hljs-number">8</span>; k++ { - <span class="hljs-keyword">if</span> (c & <span class="hljs-number">1</span>) != <span class="hljs-number">0</span> { - c = <span class="hljs-number">0xEDB88320</span> ^ (c >> <span class="hljs-number">1</span>) - } <span class="hljs-keyword">else</span> { - c = c >> <span class="hljs-number">1</span> - } - } - crcTable[n] = c - } - crcTableComputed = <span class="hljs-literal">true</span> -} - -<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">updateCrc</span><span class="hljs-params">(crc <span class="hljs-type">uint32</span>, buf []<span class="hljs-type">byte</span>)</span></span> <span class="hljs-type">uint32</span> { - <span class="hljs-keyword">if</span> !crcTableComputed { - makeCrcTable() - } - - c := crc - <span class="hljs-keyword">for</span> n := <span class="hljs-number">0</span>; n < <span class="hljs-built_in">len</span>(buf); n++ { - c = crcTable[(c^<span class="hljs-type">uint32</span>(buf[n]))&<span class="hljs-number">0xFF</span>] ^ (c >> <span class="hljs-number">8</span>) - } - <span class="hljs-keyword">return</span> c -} - -<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">crc</span><span class="hljs-params">(buf []<span class="hljs-type">byte</span>)</span></span> <span class="hljs-type">uint32</span> { - <span class="hljs-keyword">return</span> updateCrc(<span class="hljs-number">0xFFFFFFFF</span>, buf) ^ <span class="hljs-number">0xFFFFFFFF</span> -} - -<span class="hljs-keyword">const</span> adler32Base = <span class="hljs-number">65521</span> - -<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">updateAdler32</span><span class="hljs-params">(adler <span class="hljs-type">uint32</span>, buf []<span class="hljs-type">byte</span>)</span></span> <span class="hljs-type">uint32</span> { - s1 := adler & <span class="hljs-number">0xFFFF</span> - s2 := (adler >> <span class="hljs-number">16</span>) & <span class="hljs-number">0xFFFF</span> - - <span class="hljs-keyword">for</span> n := <span class="hljs-number">0</span>; n < <span class="hljs-built_in">len</span>(buf); n++ { - s1 = (s1 + <span class="hljs-type">uint32</span>(buf[n])) % adler32Base - s2 = (s2 + s1) % adler32Base - } - <span class="hljs-keyword">return</span> (s2 << <span class="hljs-number">16</span>) + s1 -} - -<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">adler32</span><span class="hljs-params">(buf []<span class="hljs-type">byte</span>)</span></span> <span class="hljs-type">uint32</span> { - <span class="hljs-keyword">return</span> updateAdler32(<span class="hljs-number">1</span>, buf) -}</code></pre> + <div class="codeblock" language="go"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">package</span><span style="color:#6F42C1"> main</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">import</span><span style="color:#24292E"> (</span></span> +<span class="line"><span style="color:#032F62"> "</span><span style="color:#6F42C1">bytes</span><span style="color:#032F62">"</span></span> +<span class="line"><span style="color:#032F62"> "</span><span style="color:#6F42C1">encoding/binary</span><span style="color:#032F62">"</span></span> +<span class="line"><span style="color:#032F62"> "</span><span style="color:#6F42C1">image</span><span style="color:#032F62">"</span></span> +<span class="line"><span style="color:#24292E"> _ </span><span style="color:#032F62">"</span><span style="color:#6F42C1">image/png</span><span style="color:#032F62">"</span></span> +<span class="line"><span style="color:#032F62"> "</span><span style="color:#6F42C1">io</span><span style="color:#032F62">"</span></span> +<span class="line"><span style="color:#032F62"> "</span><span style="color:#6F42C1">os</span><span style="color:#032F62">"</span></span> +<span class="line"><span style="color:#24292E">)</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> main</span><span style="color:#24292E">() {</span></span> +<span class="line"><span style="color:#24292E"> inFile, err </span><span style="color:#D73A49">:=</span><span style="color:#24292E"> os.</span><span style="color:#6F42C1">Open</span><span style="color:#24292E">(</span><span style="color:#032F62">"input.png"</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> err </span><span style="color:#D73A49">!=</span><span style="color:#005CC5"> nil</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#6F42C1"> panic</span><span style="color:#24292E">(err)</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#D73A49"> defer</span><span style="color:#24292E"> inFile.</span><span style="color:#6F42C1">Close</span><span style="color:#24292E">()</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E"> img, _, err </span><span style="color:#D73A49">:=</span><span style="color:#24292E"> image.</span><span style="color:#6F42C1">Decode</span><span style="color:#24292E">(inFile)</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> err </span><span style="color:#D73A49">!=</span><span style="color:#005CC5"> nil</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#6F42C1"> panic</span><span style="color:#24292E">(err)</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E"> outFile, err </span><span style="color:#D73A49">:=</span><span style="color:#24292E"> os.</span><span style="color:#6F42C1">Create</span><span style="color:#24292E">(</span><span style="color:#032F62">"output.png"</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> err </span><span style="color:#D73A49">!=</span><span style="color:#005CC5"> nil</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#6F42C1"> panic</span><span style="color:#24292E">(err)</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#D73A49"> defer</span><span style="color:#24292E"> outFile.</span><span style="color:#6F42C1">Close</span><span style="color:#24292E">()</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6F42C1"> writePng</span><span style="color:#24292E">(outFile, img)</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> writePng</span><span style="color:#24292E">(</span><span style="color:#E36209">w</span><span style="color:#6F42C1"> io</span><span style="color:#24292E">.</span><span style="color:#6F42C1">Writer</span><span style="color:#24292E">, </span><span style="color:#E36209">img</span><span style="color:#6F42C1"> image</span><span style="color:#24292E">.</span><span style="color:#6F42C1">Image</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#24292E"> width </span><span style="color:#D73A49">:=</span><span style="color:#D73A49"> uint32</span><span style="color:#24292E">(img.</span><span style="color:#6F42C1">Bounds</span><span style="color:#24292E">().</span><span style="color:#6F42C1">Dx</span><span style="color:#24292E">())</span></span> +<span class="line"><span style="color:#24292E"> height </span><span style="color:#D73A49">:=</span><span style="color:#D73A49"> uint32</span><span style="color:#24292E">(img.</span><span style="color:#6F42C1">Bounds</span><span style="color:#24292E">().</span><span style="color:#6F42C1">Dy</span><span style="color:#24292E">())</span></span> +<span class="line"><span style="color:#6F42C1"> writeSignature</span><span style="color:#24292E">(w)</span></span> +<span class="line"><span style="color:#6F42C1"> writeChunkIhdr</span><span style="color:#24292E">(w, width, height)</span></span> +<span class="line"><span style="color:#6F42C1"> writeChunkIdat</span><span style="color:#24292E">(w, width, height, img)</span></span> +<span class="line"><span style="color:#6F42C1"> writeChunkIend</span><span style="color:#24292E">(w)</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> writeSignature</span><span style="color:#24292E">(</span><span style="color:#E36209">w</span><span style="color:#6F42C1"> io</span><span style="color:#24292E">.</span><span style="color:#6F42C1">Writer</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#24292E"> sig </span><span style="color:#D73A49">:=</span><span style="color:#24292E"> [</span><span style="color:#005CC5">8</span><span style="color:#24292E">]</span><span style="color:#D73A49">uint8</span><span style="color:#24292E">{</span></span> +<span class="line"><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">89</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">50</span><span style="color:#24292E">, </span><span style="color:#6A737D">// P</span></span> +<span class="line"><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">4E</span><span style="color:#24292E">, </span><span style="color:#6A737D">// N</span></span> +<span class="line"><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">47</span><span style="color:#24292E">, </span><span style="color:#6A737D">// G</span></span> +<span class="line"><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">0D</span><span style="color:#24292E">, </span><span style="color:#6A737D">// CR</span></span> +<span class="line"><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">0A</span><span style="color:#24292E">, </span><span style="color:#6A737D">// LF</span></span> +<span class="line"><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">1A</span><span style="color:#24292E">, </span><span style="color:#6A737D">// EOF (^Z)</span></span> +<span class="line"><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">0A</span><span style="color:#24292E">, </span><span style="color:#6A737D">// LF</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(w, binary.BigEndian, sig)</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> writeChunkIhdr</span><span style="color:#24292E">(</span><span style="color:#E36209">w</span><span style="color:#6F42C1"> io</span><span style="color:#24292E">.</span><span style="color:#6F42C1">Writer</span><span style="color:#24292E">, </span><span style="color:#E36209">width</span><span style="color:#24292E">, </span><span style="color:#E36209">height</span><span style="color:#D73A49"> uint32</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#D73A49"> var</span><span style="color:#24292E"> buf </span><span style="color:#6F42C1">bytes</span><span style="color:#24292E">.</span><span style="color:#6F42C1">Buffer</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.BigEndian, width)</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.BigEndian, height)</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.BigEndian, </span><span style="color:#D73A49">uint8</span><span style="color:#24292E">(</span><span style="color:#005CC5">8</span><span style="color:#24292E">))</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.BigEndian, </span><span style="color:#D73A49">uint8</span><span style="color:#24292E">(</span><span style="color:#005CC5">2</span><span style="color:#24292E">))</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.BigEndian, </span><span style="color:#D73A49">uint8</span><span style="color:#24292E">(</span><span style="color:#005CC5">0</span><span style="color:#24292E">))</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.BigEndian, </span><span style="color:#D73A49">uint8</span><span style="color:#24292E">(</span><span style="color:#005CC5">0</span><span style="color:#24292E">))</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.BigEndian, </span><span style="color:#D73A49">uint8</span><span style="color:#24292E">(</span><span style="color:#005CC5">0</span><span style="color:#24292E">))</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6F42C1"> writeChunk</span><span style="color:#24292E">(w, </span><span style="color:#032F62">"IHDR"</span><span style="color:#24292E">, buf.</span><span style="color:#6F42C1">Bytes</span><span style="color:#24292E">())</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> writeChunkIdat</span><span style="color:#24292E">(</span><span style="color:#E36209">w</span><span style="color:#6F42C1"> io</span><span style="color:#24292E">.</span><span style="color:#6F42C1">Writer</span><span style="color:#24292E">, </span><span style="color:#E36209">width</span><span style="color:#24292E">, </span><span style="color:#E36209">height</span><span style="color:#D73A49"> uint32</span><span style="color:#24292E">, </span><span style="color:#E36209">img</span><span style="color:#6F42C1"> image</span><span style="color:#24292E">.</span><span style="color:#6F42C1">Image</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#D73A49"> var</span><span style="color:#24292E"> pixels </span><span style="color:#6F42C1">bytes</span><span style="color:#24292E">.</span><span style="color:#6F42C1">Buffer</span></span> +<span class="line"><span style="color:#D73A49"> for</span><span style="color:#24292E"> y </span><span style="color:#D73A49">:=</span><span style="color:#D73A49"> uint32</span><span style="color:#24292E">(</span><span style="color:#005CC5">0</span><span style="color:#24292E">); y </span><span style="color:#D73A49"><</span><span style="color:#24292E"> height; y</span><span style="color:#D73A49">++</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">pixels, binary.BigEndian, </span><span style="color:#D73A49">uint8</span><span style="color:#24292E">(</span><span style="color:#005CC5">0</span><span style="color:#24292E">))</span></span> +<span class="line"><span style="color:#D73A49"> for</span><span style="color:#24292E"> x </span><span style="color:#D73A49">:=</span><span style="color:#D73A49"> uint32</span><span style="color:#24292E">(</span><span style="color:#005CC5">0</span><span style="color:#24292E">); x </span><span style="color:#D73A49"><</span><span style="color:#24292E"> width; x</span><span style="color:#D73A49">++</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> r, g, b, _ </span><span style="color:#D73A49">:=</span><span style="color:#24292E"> img.</span><span style="color:#6F42C1">At</span><span style="color:#24292E">(</span><span style="color:#D73A49">int</span><span style="color:#24292E">(x), </span><span style="color:#D73A49">int</span><span style="color:#24292E">(y)).</span><span style="color:#6F42C1">RGBA</span><span style="color:#24292E">()</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">pixels, binary.BigEndian, </span><span style="color:#D73A49">uint8</span><span style="color:#24292E">(r))</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">pixels, binary.BigEndian, </span><span style="color:#D73A49">uint8</span><span style="color:#24292E">(g))</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">pixels, binary.BigEndian, </span><span style="color:#D73A49">uint8</span><span style="color:#24292E">(b))</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6F42C1"> writeChunk</span><span style="color:#24292E">(w, </span><span style="color:#032F62">"IDAT"</span><span style="color:#24292E">, </span><span style="color:#6F42C1">encodeZlib</span><span style="color:#24292E">(pixels.</span><span style="color:#6F42C1">Bytes</span><span style="color:#24292E">()))</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> encodeZlib</span><span style="color:#24292E">(</span><span style="color:#E36209">data</span><span style="color:#24292E"> []</span><span style="color:#D73A49">byte</span><span style="color:#24292E">) []</span><span style="color:#D73A49">byte</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> var</span><span style="color:#24292E"> buf </span><span style="color:#6F42C1">bytes</span><span style="color:#24292E">.</span><span style="color:#6F42C1">Buffer</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.BigEndian, </span><span style="color:#D73A49">uint8</span><span style="color:#24292E">(</span><span style="color:#D73A49">0x</span><span style="color:#005CC5">78</span><span style="color:#24292E">))</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.BigEndian, </span><span style="color:#D73A49">uint8</span><span style="color:#24292E">(</span><span style="color:#D73A49">0x</span><span style="color:#005CC5">01</span><span style="color:#24292E">))</span></span> +<span class="line"><span style="color:#24292E"> blockSize </span><span style="color:#D73A49">:=</span><span style="color:#005CC5"> 65535</span></span> +<span class="line"><span style="color:#24292E"> isFinalBlock </span><span style="color:#D73A49">:=</span><span style="color:#005CC5"> false</span></span> +<span class="line"><span style="color:#D73A49"> for</span><span style="color:#24292E"> i </span><span style="color:#D73A49">:=</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">; </span><span style="color:#D73A49">!</span><span style="color:#24292E">isFinalBlock; i</span><span style="color:#D73A49">++</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> var</span><span style="color:#24292E"> block []</span><span style="color:#D73A49">byte</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#6F42C1"> len</span><span style="color:#24292E">(data) </span><span style="color:#D73A49"><=</span><span style="color:#24292E"> (i</span><span style="color:#D73A49">+</span><span style="color:#005CC5">1</span><span style="color:#24292E">)</span><span style="color:#D73A49">*</span><span style="color:#24292E">blockSize {</span></span> +<span class="line"><span style="color:#24292E"> block </span><span style="color:#D73A49">=</span><span style="color:#24292E"> data[i</span><span style="color:#D73A49">*</span><span style="color:#24292E">blockSize:]</span></span> +<span class="line"><span style="color:#24292E"> isFinalBlock </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> true</span></span> +<span class="line"><span style="color:#24292E"> } </span><span style="color:#D73A49">else</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> block </span><span style="color:#D73A49">=</span><span style="color:#24292E"> data[i</span><span style="color:#D73A49">*</span><span style="color:#24292E">blockSize : (i</span><span style="color:#D73A49">+</span><span style="color:#005CC5">1</span><span style="color:#24292E">)</span><span style="color:#D73A49">*</span><span style="color:#24292E">blockSize]</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.BigEndian, isFinalBlock)</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.LittleEndian, </span><span style="color:#D73A49">uint16</span><span style="color:#24292E">(</span><span style="color:#6F42C1">len</span><span style="color:#24292E">(block)))</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.LittleEndian, </span><span style="color:#D73A49">uint16</span><span style="color:#24292E">(</span><span style="color:#D73A49">^</span><span style="color:#6F42C1">len</span><span style="color:#24292E">(block)))</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.LittleEndian, block)</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(</span><span style="color:#D73A49">&</span><span style="color:#24292E">buf, binary.BigEndian, </span><span style="color:#6F42C1">adler32</span><span style="color:#24292E">(data))</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#24292E"> buf.</span><span style="color:#6F42C1">Bytes</span><span style="color:#24292E">()</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> writeChunkIend</span><span style="color:#24292E">(</span><span style="color:#E36209">w</span><span style="color:#6F42C1"> io</span><span style="color:#24292E">.</span><span style="color:#6F42C1">Writer</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#6F42C1"> writeChunk</span><span style="color:#24292E">(w, </span><span style="color:#032F62">"IEND"</span><span style="color:#24292E">, </span><span style="color:#005CC5">nil</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> writeChunk</span><span style="color:#24292E">(</span><span style="color:#E36209">w</span><span style="color:#6F42C1"> io</span><span style="color:#24292E">.</span><span style="color:#6F42C1">Writer</span><span style="color:#24292E">, </span><span style="color:#E36209">chunkType</span><span style="color:#D73A49"> string</span><span style="color:#24292E">, </span><span style="color:#E36209">data</span><span style="color:#24292E"> []</span><span style="color:#D73A49">byte</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#24292E"> typeAndData </span><span style="color:#D73A49">:=</span><span style="color:#6F42C1"> make</span><span style="color:#24292E">([]</span><span style="color:#D73A49">byte</span><span style="color:#24292E">, </span><span style="color:#005CC5">0</span><span style="color:#24292E">, </span><span style="color:#6F42C1">len</span><span style="color:#24292E">(chunkType)</span><span style="color:#D73A49">+</span><span style="color:#6F42C1">len</span><span style="color:#24292E">(data))</span></span> +<span class="line"><span style="color:#24292E"> typeAndData </span><span style="color:#D73A49">=</span><span style="color:#6F42C1"> append</span><span style="color:#24292E">(typeAndData, []</span><span style="color:#D73A49">byte</span><span style="color:#24292E">(chunkType)</span><span style="color:#D73A49">...</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#24292E"> typeAndData </span><span style="color:#D73A49">=</span><span style="color:#6F42C1"> append</span><span style="color:#24292E">(typeAndData, data</span><span style="color:#D73A49">...</span><span style="color:#24292E">)</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(w, binary.BigEndian, </span><span style="color:#D73A49">uint32</span><span style="color:#24292E">(</span><span style="color:#6F42C1">len</span><span style="color:#24292E">(data)))</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(w, binary.BigEndian, typeAndData)</span></span> +<span class="line"><span style="color:#24292E"> binary.</span><span style="color:#6F42C1">Write</span><span style="color:#24292E">(w, binary.BigEndian, </span><span style="color:#6F42C1">crc</span><span style="color:#24292E">(typeAndData))</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">var</span><span style="color:#24292E"> (</span></span> +<span class="line"><span style="color:#24292E"> crcTable [</span><span style="color:#005CC5">256</span><span style="color:#24292E">]</span><span style="color:#D73A49">uint32</span></span> +<span class="line"><span style="color:#24292E"> crcTableComputed </span><span style="color:#D73A49">bool</span></span> +<span class="line"><span style="color:#24292E">)</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> makeCrcTable</span><span style="color:#24292E">() {</span></span> +<span class="line"><span style="color:#D73A49"> for</span><span style="color:#24292E"> n </span><span style="color:#D73A49">:=</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">; n </span><span style="color:#D73A49"><</span><span style="color:#005CC5"> 256</span><span style="color:#24292E">; n</span><span style="color:#D73A49">++</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> c </span><span style="color:#D73A49">:=</span><span style="color:#D73A49"> uint32</span><span style="color:#24292E">(n)</span></span> +<span class="line"><span style="color:#D73A49"> for</span><span style="color:#24292E"> k </span><span style="color:#D73A49">:=</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">; k </span><span style="color:#D73A49"><</span><span style="color:#005CC5"> 8</span><span style="color:#24292E">; k</span><span style="color:#D73A49">++</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> (c </span><span style="color:#D73A49">&</span><span style="color:#005CC5"> 1</span><span style="color:#24292E">) </span><span style="color:#D73A49">!=</span><span style="color:#005CC5"> 0</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> c </span><span style="color:#D73A49">=</span><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">EDB88320</span><span style="color:#D73A49"> ^</span><span style="color:#24292E"> (c </span><span style="color:#D73A49">>></span><span style="color:#005CC5"> 1</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#24292E"> } </span><span style="color:#D73A49">else</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> c </span><span style="color:#D73A49">=</span><span style="color:#24292E"> c </span><span style="color:#D73A49">>></span><span style="color:#005CC5"> 1</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E"> crcTable[n] </span><span style="color:#D73A49">=</span><span style="color:#24292E"> c</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E"> crcTableComputed </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> true</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> updateCrc</span><span style="color:#24292E">(</span><span style="color:#E36209">crc</span><span style="color:#D73A49"> uint32</span><span style="color:#24292E">, </span><span style="color:#E36209">buf</span><span style="color:#24292E"> []</span><span style="color:#D73A49">byte</span><span style="color:#24292E">) </span><span style="color:#D73A49">uint32</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#D73A49"> !</span><span style="color:#24292E">crcTableComputed {</span></span> +<span class="line"><span style="color:#6F42C1"> makeCrcTable</span><span style="color:#24292E">()</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E"> c </span><span style="color:#D73A49">:=</span><span style="color:#24292E"> crc</span></span> +<span class="line"><span style="color:#D73A49"> for</span><span style="color:#24292E"> n </span><span style="color:#D73A49">:=</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">; n </span><span style="color:#D73A49"><</span><span style="color:#6F42C1"> len</span><span style="color:#24292E">(buf); n</span><span style="color:#D73A49">++</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> c </span><span style="color:#D73A49">=</span><span style="color:#24292E"> crcTable[(c</span><span style="color:#D73A49">^uint32</span><span style="color:#24292E">(buf[n]))</span><span style="color:#D73A49">&0x</span><span style="color:#005CC5">FF</span><span style="color:#24292E">] </span><span style="color:#D73A49">^</span><span style="color:#24292E"> (c </span><span style="color:#D73A49">>></span><span style="color:#005CC5"> 8</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#24292E"> c</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> crc</span><span style="color:#24292E">(</span><span style="color:#E36209">buf</span><span style="color:#24292E"> []</span><span style="color:#D73A49">byte</span><span style="color:#24292E">) </span><span style="color:#D73A49">uint32</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#6F42C1"> updateCrc</span><span style="color:#24292E">(</span><span style="color:#D73A49">0x</span><span style="color:#005CC5">FFFFFFFF</span><span style="color:#24292E">, buf) </span><span style="color:#D73A49">^</span><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">FFFFFFFF</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">const</span><span style="color:#005CC5"> adler32Base</span><span style="color:#D73A49"> =</span><span style="color:#005CC5"> 65521</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> updateAdler32</span><span style="color:#24292E">(</span><span style="color:#E36209">adler</span><span style="color:#D73A49"> uint32</span><span style="color:#24292E">, </span><span style="color:#E36209">buf</span><span style="color:#24292E"> []</span><span style="color:#D73A49">byte</span><span style="color:#24292E">) </span><span style="color:#D73A49">uint32</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> s1 </span><span style="color:#D73A49">:=</span><span style="color:#24292E"> adler </span><span style="color:#D73A49">&</span><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">FFFF</span></span> +<span class="line"><span style="color:#24292E"> s2 </span><span style="color:#D73A49">:=</span><span style="color:#24292E"> (adler </span><span style="color:#D73A49">>></span><span style="color:#005CC5"> 16</span><span style="color:#24292E">) </span><span style="color:#D73A49">&</span><span style="color:#D73A49"> 0x</span><span style="color:#005CC5">FFFF</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49"> for</span><span style="color:#24292E"> n </span><span style="color:#D73A49">:=</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">; n </span><span style="color:#D73A49"><</span><span style="color:#6F42C1"> len</span><span style="color:#24292E">(buf); n</span><span style="color:#D73A49">++</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> s1 </span><span style="color:#D73A49">=</span><span style="color:#24292E"> (s1 </span><span style="color:#D73A49">+</span><span style="color:#D73A49"> uint32</span><span style="color:#24292E">(buf[n])) </span><span style="color:#D73A49">%</span><span style="color:#24292E"> adler32Base</span></span> +<span class="line"><span style="color:#24292E"> s2 </span><span style="color:#D73A49">=</span><span style="color:#24292E"> (s2 </span><span style="color:#D73A49">+</span><span style="color:#24292E"> s1) </span><span style="color:#D73A49">%</span><span style="color:#24292E"> adler32Base</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#24292E"> (s2 </span><span style="color:#D73A49"><<</span><span style="color:#005CC5"> 16</span><span style="color:#24292E">) </span><span style="color:#D73A49">+</span><span style="color:#24292E"> s1</span></span> +<span class="line"><span style="color:#24292E">}</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">func</span><span style="color:#6F42C1"> adler32</span><span style="color:#24292E">(</span><span style="color:#E36209">buf</span><span style="color:#24292E"> []</span><span style="color:#D73A49">byte</span><span style="color:#24292E">) </span><span style="color:#D73A49">uint32</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#6F42C1"> updateAdler32</span><span style="color:#24292E">(</span><span style="color:#005CC5">1</span><span style="color:#24292E">, buf)</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> </section> <section id="section--references"> diff --git a/vhosts/blog/public/posts/2023-04-04/phperkaigi-2023-report/index.html b/vhosts/blog/public/posts/2023-04-04/phperkaigi-2023-report/index.html index de619ab8..5f6c6bec 100644 --- a/vhosts/blog/public/posts/2023-04-04/phperkaigi-2023-report/index.html +++ b/vhosts/blog/public/posts/2023-04-04/phperkaigi-2023-report/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>PHPerKaigi 2023 参加レポ|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> diff --git a/vhosts/blog/public/posts/2023-06-25/phpconfuk-2023-report/index.html b/vhosts/blog/public/posts/2023-06-25/phpconfuk-2023-report/index.html index 93fe3e09..8e2d179f 100644 --- a/vhosts/blog/public/posts/2023-06-25/phpconfuk-2023-report/index.html +++ b/vhosts/blog/public/posts/2023-06-25/phpconfuk-2023-report/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>PHP カンファレンス福岡 2023 参加レポ|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> diff --git a/vhosts/blog/public/posts/2023-10-02/compile-php-runtime-to-wasm/index.html b/vhosts/blog/public/posts/2023-10-02/compile-php-runtime-to-wasm/index.html index 0e00dead..35252f62 100644 --- a/vhosts/blog/public/posts/2023-10-02/compile-php-runtime-to-wasm/index.html +++ b/vhosts/blog/public/posts/2023-10-02/compile-php-runtime-to-wasm/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>PHP の処理系を Emscripten で WebAssembly にコンパイルする|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -111,18 +110,20 @@ 先にこの記事のゴールを示しておく。これから示す手順のとおりに進めると、次のようなコードが動くようになる。このコードはこのあと使うので、<code>index.mjs</code> の名前で保存しておくこと。 </p> - <pre class="highlight" language="javascript"><code class="highlight"><span class="hljs-keyword">import</span> { readFile } <span class="hljs-keyword">from</span> <span class="hljs-string">'node:fs/promises'</span>; -<span class="hljs-keyword">import</span> <span class="hljs-title class_">PHPWasm</span> <span class="hljs-keyword">from</span> <span class="hljs-string">'./php-wasm.mjs'</span> - -<span class="hljs-keyword">const</span> code = <span class="hljs-keyword">await</span> <span class="hljs-title function_">readFile</span>(<span class="hljs-string">'/dev/stdin'</span>, { <span class="hljs-attr">encoding</span>: <span class="hljs-string">'utf-8'</span> }); - -<span class="hljs-keyword">const</span> { ccall } = <span class="hljs-keyword">await</span> <span class="hljs-title class_">PHPWasm</span>(); -<span class="hljs-keyword">const</span> result = <span class="hljs-title function_">ccall</span>( - <span class="hljs-string">'php_wasm_run'</span>, - <span class="hljs-string">'number'</span>, [<span class="hljs-string">'string'</span>], - [code], -); -<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">`exit code: <span class="hljs-subst">${result}</span>`</span>);</code></pre> + <div class="codeblock" language="javascript"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">import</span><span style="color:#24292E"> { readFile } </span><span style="color:#D73A49">from</span><span style="color:#032F62"> 'node:fs/promises'</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">import</span><span style="color:#24292E"> PHPWasm </span><span style="color:#D73A49">from</span><span style="color:#032F62"> './php-wasm.mjs'</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">const</span><span style="color:#005CC5"> code</span><span style="color:#D73A49"> =</span><span style="color:#D73A49"> await</span><span style="color:#6F42C1"> readFile</span><span style="color:#24292E">(</span><span style="color:#032F62">'/dev/stdin'</span><span style="color:#24292E">, { encoding: </span><span style="color:#032F62">'utf-8'</span><span style="color:#24292E"> });</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">const</span><span style="color:#24292E"> { </span><span style="color:#005CC5">ccall</span><span style="color:#24292E"> } </span><span style="color:#D73A49">=</span><span style="color:#D73A49"> await</span><span style="color:#6F42C1"> PHPWasm</span><span style="color:#24292E">();</span></span> +<span class="line"><span style="color:#D73A49">const</span><span style="color:#005CC5"> result</span><span style="color:#D73A49"> =</span><span style="color:#6F42C1"> ccall</span><span style="color:#24292E">(</span></span> +<span class="line"><span style="color:#032F62"> 'php_wasm_run'</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#032F62"> 'number'</span><span style="color:#24292E">, [</span><span style="color:#032F62">'string'</span><span style="color:#24292E">],</span></span> +<span class="line"><span style="color:#24292E"> [code],</span></span> +<span class="line"><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E">console.</span><span style="color:#6F42C1">log</span><span style="color:#24292E">(</span><span style="color:#032F62">`exit code: ${</span><span style="color:#24292E">result</span><span style="color:#032F62">}`</span><span style="color:#24292E">);</span></span></code></pre> + </div> <p> 標準入力から与えたコードを WebAssembly にコンパイルされた PHP 処理系の上で実行している。このような <code>php-wasm.mjs</code> (とそこから呼び出される <code>php-wasm.wasm</code>) を作成する。 @@ -137,30 +138,32 @@ 先ほどのコードでも使っていたエントリポイントである <code>php_wasm_run</code> を用意する。 </p> - <pre class="highlight" language="c"><code class="highlight"><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><stdio.h></span></span> -<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><emscripten.h></span></span> -<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><Zend/zend_execute.h></span></span> -<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><sapi/embed/php_embed.h></span></span> - -<span class="hljs-type">int</span> EMSCRIPTEN_KEEPALIVE <span class="hljs-title function_">php_wasm_run</span><span class="hljs-params">(<span class="hljs-type">const</span> <span class="hljs-type">char</span>* code)</span> { - zend_result result; - - <span class="hljs-type">int</span> argc = <span class="hljs-number">1</span>; - <span class="hljs-type">char</span>* argv[] = { <span class="hljs-string">"php.wasm"</span>, <span class="hljs-literal">NULL</span> }; - - PHP_EMBED_START_BLOCK(argc, argv); - - result = zend_eval_string_ex(code, <span class="hljs-literal">NULL</span>, <span class="hljs-string">"php.wasm code"</span>, <span class="hljs-number">1</span>); - - PHP_EMBED_END_BLOCK(); - - <span class="hljs-built_in">fprintf</span>(<span class="hljs-built_in">stdout</span>, <span class="hljs-string">"\n"</span>); - fflush(<span class="hljs-built_in">stdout</span>); - <span class="hljs-built_in">fprintf</span>(<span class="hljs-built_in">stderr</span>, <span class="hljs-string">"\n"</span>); - fflush(<span class="hljs-built_in">stderr</span>); - - <span class="hljs-keyword">return</span> result == SUCCESS ? <span class="hljs-number">0</span> : <span class="hljs-number">1</span>; -}</code></pre> + <div class="codeblock" language="c"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">#include</span><span style="color:#032F62"> <stdio.h></span></span> +<span class="line"><span style="color:#D73A49">#include</span><span style="color:#032F62"> <emscripten.h></span></span> +<span class="line"><span style="color:#D73A49">#include</span><span style="color:#032F62"> <Zend/zend_execute.h></span></span> +<span class="line"><span style="color:#D73A49">#include</span><span style="color:#032F62"> <sapi/embed/php_embed.h></span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">int</span><span style="color:#24292E"> EMSCRIPTEN_KEEPALIVE </span><span style="color:#6F42C1">php_wasm_run</span><span style="color:#24292E">(</span><span style="color:#D73A49">const</span><span style="color:#D73A49"> char*</span><span style="color:#E36209"> code</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#24292E"> zend_result result;</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49"> int</span><span style="color:#24292E"> argc </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> 1</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49"> char*</span><span style="color:#24292E"> argv</span><span style="color:#D73A49">[]</span><span style="color:#D73A49"> =</span><span style="color:#24292E"> { </span><span style="color:#032F62">"php.wasm"</span><span style="color:#24292E">, </span><span style="color:#005CC5">NULL</span><span style="color:#24292E"> };</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6F42C1"> PHP_EMBED_START_BLOCK</span><span style="color:#24292E">(argc, argv);</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E"> result </span><span style="color:#D73A49">=</span><span style="color:#6F42C1"> zend_eval_string_ex</span><span style="color:#24292E">(code, </span><span style="color:#005CC5">NULL</span><span style="color:#24292E">, </span><span style="color:#032F62">"php.wasm code"</span><span style="color:#24292E">, </span><span style="color:#005CC5">1</span><span style="color:#24292E">);</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6F42C1"> PHP_EMBED_END_BLOCK</span><span style="color:#24292E">();</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6F42C1"> fprintf</span><span style="color:#24292E">(stdout, </span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#6F42C1"> fflush</span><span style="color:#24292E">(stdout);</span></span> +<span class="line"><span style="color:#6F42C1"> fprintf</span><span style="color:#24292E">(stderr, </span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#6F42C1"> fflush</span><span style="color:#24292E">(stderr);</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#24292E"> result </span><span style="color:#D73A49">==</span><span style="color:#24292E"> SUCCESS </span><span style="color:#D73A49">?</span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> :</span><span style="color:#005CC5"> 1</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> ほとんどはただの PHP の公開 API を使ったコードだが、Emscripten 向けの注意点が 2点ある。 @@ -185,49 +188,55 @@ まずは <a href="https://hub.docker.com/r/emscripten/emsdk" rel="noreferrer" target="_blank">Emscripten 公式が提供している Docker イメージ</a>を使って、PHP 処理系と先ほど示した C 言語のソースコードを WebAssembly にコンパイルする。 </p> - <pre class="highlight" language="dockerfile"><code class="highlight"><span class="hljs-keyword">FROM</span> emscripten/emsdk:<span class="hljs-number">3.1</span>.<span class="hljs-number">46</span> AS wasm-builder</code></pre> + <div class="codeblock" language="dockerfile"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">FROM</span><span style="color:#24292E"> emscripten/emsdk:3.1.46 </span><span style="color:#D73A49">AS</span><span style="color:#24292E"> wasm-builder</span></span></code></pre> + </div> <p> 次に、<a href="https://github.com/php/php-src" rel="noreferrer" target="_blank">php/php-src</a> から PHP 処理系のソースコードを取得し、ビルドに必要な apt パッケージを取ってくる。有効にする拡張を増やしたいなら、ここでインストールするパッケージも増やすことになるだろう。 </p> - <pre class="highlight" language="dockerfile"><code class="highlight"><span class="hljs-keyword">RUN</span><span class="language-bash"> git <span class="hljs-built_in">clone</span> --depth=1 --branch=php-8.2.10 https://github.com/php/php-src</span> - -<span class="hljs-keyword">RUN</span><span class="language-bash"> apt-get update && \ - apt-get install -y --no-install-recommends \ - autoconf \ - bison \ - pkg-config \ - re2c \ - && \ - :</span></code></pre> + <div class="codeblock" language="dockerfile"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">RUN</span><span style="color:#24292E"> git clone --depth=1 --branch=php-8.2.10 https://github.com/php/php-src</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">RUN</span><span style="color:#24292E"> apt-get update && \</span></span> +<span class="line"><span style="color:#24292E"> apt-get install -y --no-install-recommends \</span></span> +<span class="line"><span style="color:#24292E"> autoconf \</span></span> +<span class="line"><span style="color:#24292E"> bison \</span></span> +<span class="line"><span style="color:#24292E"> pkg-config \</span></span> +<span class="line"><span style="color:#24292E"> re2c \</span></span> +<span class="line"><span style="color:#24292E"> && \</span></span> +<span class="line"><span style="color:#24292E"> :</span></span></code></pre> + </div> <p> 続けて、Emscripten のツールチェインを用いて PHP 処理系をビルドする。 </p> - <pre class="highlight" language="dockerfile"><code class="highlight"><span class="hljs-keyword">RUN</span><span class="language-bash"> <span class="hljs-built_in">cd</span> php-src && \ - ./buildconf --force && \ - emconfigure ./configure \ - --disable-all \ - --disable-mbregex \ - --disable-fiber-asm \ - --disable-cli \ - --disable-cgi \ - --disable-phpdbg \ - --enable-embed=static \ - --enable-mbstring \ - --without-iconv \ - --without-libxml \ - --without-pcre-jit \ - --without-pdo-sqlite \ - --without-sqlite3 \ - && \ - EMCC_CFLAGS=<span class="hljs-string">'-s ERROR_ON_UNDEFINED_SYMBOLS=0'</span> emmake make -j$(<span class="hljs-built_in">nproc</span>) && \ - <span class="hljs-built_in">mv</span> libs/libphp.a .. && \ - make clean && \ - git clean -fd && \ - :</span></code></pre> + <div class="codeblock" language="dockerfile"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">RUN</span><span style="color:#24292E"> cd php-src && \</span></span> +<span class="line"><span style="color:#24292E"> ./buildconf --force && \</span></span> +<span class="line"><span style="color:#24292E"> emconfigure ./configure \</span></span> +<span class="line"><span style="color:#24292E"> --disable-all \</span></span> +<span class="line"><span style="color:#24292E"> --disable-mbregex \</span></span> +<span class="line"><span style="color:#24292E"> --disable-fiber-asm \</span></span> +<span class="line"><span style="color:#24292E"> --disable-cli \</span></span> +<span class="line"><span style="color:#24292E"> --disable-cgi \</span></span> +<span class="line"><span style="color:#24292E"> --disable-phpdbg \</span></span> +<span class="line"><span style="color:#24292E"> --enable-embed=static \</span></span> +<span class="line"><span style="color:#24292E"> --enable-mbstring \</span></span> +<span class="line"><span style="color:#24292E"> --without-iconv \</span></span> +<span class="line"><span style="color:#24292E"> --without-libxml \</span></span> +<span class="line"><span style="color:#24292E"> --without-pcre-jit \</span></span> +<span class="line"><span style="color:#24292E"> --without-pdo-sqlite \</span></span> +<span class="line"><span style="color:#24292E"> --without-sqlite3 \</span></span> +<span class="line"><span style="color:#24292E"> && \</span></span> +<span class="line"><span style="color:#24292E"> EMCC_CFLAGS=</span><span style="color:#032F62">'-s ERROR_ON_UNDEFINED_SYMBOLS=0'</span><span style="color:#24292E"> emmake make -j$(nproc) && \</span></span> +<span class="line"><span style="color:#24292E"> mv libs/libphp.a .. && \</span></span> +<span class="line"><span style="color:#24292E"> make clean && \</span></span> +<span class="line"><span style="color:#24292E"> git clean -fd && \</span></span> +<span class="line"><span style="color:#24292E"> :</span></span></code></pre> + </div> <p> ここまでと比べると少し複雑なので、それぞれ詳しく見ていこう。 @@ -257,22 +266,24 @@ さて、PHP 処理系をライブラリ化できたので、次に先ほど載せた C のソースコードをビルドしていこう。<code>Dockerfile</code> と同じ場所に <code>php-wasm.c</code> という名前で保存し、次のようにする。 </p> - <pre class="highlight" language="dockerfile"><code class="highlight"><span class="hljs-keyword">COPY</span><span class="language-bash"> php-wasm.c /src/</span> - -<span class="hljs-keyword">RUN</span><span class="language-bash"> <span class="hljs-built_in">cd</span> php-src && \ - emcc \ - -c \ - -o php-wasm.o \ - -I . \ - -I TSRM \ - -I Zend \ - -I main \ - ../php-wasm.c \ - && \ - <span class="hljs-built_in">mv</span> php-wasm.o .. && \ - make clean && \ - git clean -fd && \ - :</span></code></pre> + <div class="codeblock" language="dockerfile"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">COPY</span><span style="color:#24292E"> php-wasm.c /src/</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">RUN</span><span style="color:#24292E"> cd php-src && \</span></span> +<span class="line"><span style="color:#24292E"> emcc \</span></span> +<span class="line"><span style="color:#24292E"> -c \</span></span> +<span class="line"><span style="color:#24292E"> -o php-wasm.o \</span></span> +<span class="line"><span style="color:#24292E"> -I . \</span></span> +<span class="line"><span style="color:#24292E"> -I TSRM \</span></span> +<span class="line"><span style="color:#24292E"> -I Zend \</span></span> +<span class="line"><span style="color:#24292E"> -I main \</span></span> +<span class="line"><span style="color:#24292E"> ../php-wasm.c \</span></span> +<span class="line"><span style="color:#24292E"> && \</span></span> +<span class="line"><span style="color:#24292E"> mv php-wasm.o .. && \</span></span> +<span class="line"><span style="color:#24292E"> make clean && \</span></span> +<span class="line"><span style="color:#24292E"> git clean -fd && \</span></span> +<span class="line"><span style="color:#24292E"> :</span></span></code></pre> + </div> <p> <code>emcc</code> は <code>cc</code> (C コンパイラ/リンカ) の Emscripten 版で、<code>-c</code> は「コンパイル」の意。<code>-o</code> や <code>-I</code> は普通の C コンパイラと同様、出力ファイルの指定とインクルードパスの指定である。 @@ -282,18 +293,20 @@ <code>libphp.a</code> と <code>php-wasm.o</code> が手に入ったので、これらをリンクして WebAssembly のバイナリとそのラッパである JavaScript ファイルを生成する。これにも <code>emcc</code> コマンドを使う。 </p> - <pre class="highlight" language="dockerfile"><code class="highlight"><span class="hljs-keyword">RUN</span><span class="language-bash"> emcc \ - -s ENVIRONMENT=node \ - -s ERROR_ON_UNDEFINED_SYMBOLS=0 \ - -s EXPORTED_RUNTIME_METHODS=<span class="hljs-string">'["ccall"]'</span> \ - -s EXPORT_ES6=1 \ - -s INITIAL_MEMORY=16777216 \ - -s INVOKE_RUN=0 \ - -s MODULARIZE=1 \ - -o php-wasm.js \ - php-wasm.o \ - libphp.a \ - ;</span></code></pre> + <div class="codeblock" language="dockerfile"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">RUN</span><span style="color:#24292E"> emcc \</span></span> +<span class="line"><span style="color:#24292E"> -s ENVIRONMENT=node \</span></span> +<span class="line"><span style="color:#24292E"> -s ERROR_ON_UNDEFINED_SYMBOLS=0 \</span></span> +<span class="line"><span style="color:#24292E"> -s EXPORTED_RUNTIME_METHODS=</span><span style="color:#032F62">'["ccall"]'</span><span style="color:#24292E"> \</span></span> +<span class="line"><span style="color:#24292E"> -s EXPORT_ES6=1 \</span></span> +<span class="line"><span style="color:#24292E"> -s INITIAL_MEMORY=16777216 \</span></span> +<span class="line"><span style="color:#24292E"> -s INVOKE_RUN=0 \</span></span> +<span class="line"><span style="color:#24292E"> -s MODULARIZE=1 \</span></span> +<span class="line"><span style="color:#24292E"> -o php-wasm.js \</span></span> +<span class="line"><span style="color:#24292E"> php-wasm.o \</span></span> +<span class="line"><span style="color:#24292E"> libphp.a \</span></span> +<span class="line"><span style="color:#24292E"> ;</span></span></code></pre> + </div> <p> それぞれのフラグについて解説する。 @@ -335,14 +348,16 @@ といっても、Node.js はビルトインで WebAssembly をサポートしているので、ほとんどやることはない。先ほど掲載した JavaScript のコードは、<code>Dockerfile</code> と同じディレクトリに <code>index.mjs</code> で配置すること。 </p> - <pre class="highlight" language="dockerfile"><code class="highlight"><span class="hljs-keyword">FROM</span> node:<span class="hljs-number">20.7</span> - -<span class="hljs-keyword">WORKDIR</span><span class="language-bash"> /app</span> -<span class="hljs-keyword">COPY</span><span class="language-bash"> --from=wasm-builder /src/php-wasm.js /app/php-wasm.mjs</span> -<span class="hljs-keyword">COPY</span><span class="language-bash"> --from=wasm-builder /src/php-wasm.wasm /app/php-wasm.wasm</span> -<span class="hljs-keyword">COPY</span><span class="language-bash"> index.mjs /app/</span> - -<span class="hljs-keyword">ENTRYPOINT</span><span class="language-bash"> [<span class="hljs-string">"node"</span>, <span class="hljs-string">"index.mjs"</span>]</span></code></pre> + <div class="codeblock" language="dockerfile"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">FROM</span><span style="color:#24292E"> node:20.7</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">WORKDIR</span><span style="color:#24292E"> /app</span></span> +<span class="line"><span style="color:#D73A49">COPY</span><span style="color:#24292E"> --from=wasm-builder /src/php-wasm.js /app/php-wasm.mjs</span></span> +<span class="line"><span style="color:#D73A49">COPY</span><span style="color:#24292E"> --from=wasm-builder /src/php-wasm.wasm /app/php-wasm.wasm</span></span> +<span class="line"><span style="color:#D73A49">COPY</span><span style="color:#24292E"> index.mjs /app/</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">ENTRYPOINT</span><span style="color:#24292E"> [</span><span style="color:#032F62">"node"</span><span style="color:#24292E">, </span><span style="color:#032F62">"index.mjs"</span><span style="color:#24292E">]</span></span></code></pre> + </div> </section> </section> @@ -352,12 +367,14 @@ <code>Dockerfile</code>、<code>php-wasm.c</code>、<code>index.mjs</code> を用意したら、Docker コンテナをビルドして実行する。 </p> - <pre class="highlight" language="dockerfile"><code class="highlight">$ docker build -t php-wasm . -$ echo <span class="hljs-string">'echo "Hello, World!", PHP_EOL;'</span> | docker <span class="hljs-keyword">run</span><span class="language-bash"> --<span class="hljs-built_in">rm</span> -i php-wasm</span> -Hello, World! - - -exit code: <span class="hljs-number">0</span></code></pre> + <div class="codeblock" language="dockerfile"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$ docker build -t php-wasm .</span></span> +<span class="line"><span style="color:#24292E">$ echo </span><span style="color:#032F62">'echo "Hello, World!", PHP_EOL;'</span><span style="color:#24292E"> | docker run --rm -i php-wasm</span></span> +<span class="line"><span style="color:#24292E">Hello, World!</span></span> +<span class="line"></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">exit code: 0</span></span></code></pre> + </div> </section> <section id="section--outro"> diff --git a/vhosts/blog/public/posts/2023-10-13/i-entered-the-open-university-of-japan/index.html b/vhosts/blog/public/posts/2023-10-13/i-entered-the-open-university-of-japan/index.html index d6c63557..ac13669c 100644 --- a/vhosts/blog/public/posts/2023-10-13/i-entered-the-open-university-of-japan/index.html +++ b/vhosts/blog/public/posts/2023-10-13/i-entered-the-open-university-of-japan/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>放送大学に入学しました|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> diff --git a/vhosts/blog/public/posts/2023-12-03/isucon-13/index.html b/vhosts/blog/public/posts/2023-12-03/isucon-13/index.html index fdc94f3a..63f6e8f4 100644 --- a/vhosts/blog/public/posts/2023-12-03/isucon-13/index.html +++ b/vhosts/blog/public/posts/2023-12-03/isucon-13/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>ISUCON 13 に参加した|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> diff --git a/vhosts/blog/public/posts/2023-12-31/2023-reflections/index.html b/vhosts/blog/public/posts/2023-12-31/2023-reflections/index.html index 1e4f364b..355f11bd 100644 --- a/vhosts/blog/public/posts/2023-12-31/2023-reflections/index.html +++ b/vhosts/blog/public/posts/2023-12-31/2023-reflections/index.html @@ -13,8 +13,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>2023年の振り返り|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> diff --git a/vhosts/blog/public/posts/2024-01-10/neovim-insert-namespace-declaration-to-empty-php-file/index.html b/vhosts/blog/public/posts/2024-01-10/neovim-insert-namespace-declaration-to-empty-php-file/index.html index 1e7cd5ee..07043627 100644 --- a/vhosts/blog/public/posts/2024-01-10/neovim-insert-namespace-declaration-to-empty-php-file/index.html +++ b/vhosts/blog/public/posts/2024-01-10/neovim-insert-namespace-declaration-to-empty-php-file/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>【Neovim】 空の PHP ファイルに namespace 宣言を挿入する|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -76,17 +75,21 @@ Neovim で空の PHP ファイルを開いたとき、そのファイルが置かれているディレクトリの構造に基づいて、自動的に <code>namespace</code> 宣言を挿入したい。具体的には、トップレベルの名前空間が <code>MyNamespace</code> であり、ファイル <code>src/Foo/Bar/Baz.php</code> を開いたときに、そのファイルが空であるなら、次のようなテンプレートが自動的に挿入されてほしい。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> - -<span class="hljs-keyword">namespace</span> <span class="hljs-title class_">MyNamespace</span>\<span class="hljs-title class_">Foo</span>\<span class="hljs-title class_">Bar</span>;</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">namespace</span><span style="color:#6F42C1"> MyNamespace\Foo\Bar</span><span style="color:#24292E">;</span></span></code></pre> + </div> </section> <section id="section--version"> <h2><a href="#section--version">バージョン情報</a></h2> - <pre class="highlight"><code>$ nvim --version -NVIM v0.9.2 -Build type: Release -LuaJIT 2.1.1693350652</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ nvim --version</span></span> +<span class="line"><span>NVIM v0.9.2</span></span> +<span class="line"><span>Build type: Release</span></span> +<span class="line"><span>LuaJIT 2.1.1693350652</span></span></code></pre> + </div> <p> 今回は Lua で処理を記述したため、Vim では動作しない。以下の説明でも Neovim に絞って述べる。また、パス区切りがスラッシュである前提で記述したため、Windows には対応していない。 @@ -114,13 +117,15 @@ LuaJIT 2.1.1693350652</code></pre> ファイルタイプは読み込んだあとに変更されることもあるので、ftplugin は複数回実行されうる。二重読み込みを防ぐために、<code>did_ftplugin_<FILE_TYPE>_after</code> というバッファローカル変数を定義しておくのが慣習となっている。 </p> - <pre class="highlight" language="lua"><code class="highlight"><span class="hljs-keyword">if</span> vim.b.did_ftplugin_php_after <span class="hljs-keyword">then</span> - <span class="hljs-keyword">return</span> -<span class="hljs-keyword">end</span> - -<span class="hljs-comment">-- ここに実際の処理を書く</span> - -vim.b.did_ftplugin_php_after = <span class="hljs-literal">true</span></code></pre> + <div class="codeblock" language="lua"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">if</span><span style="color:#24292E"> vim.</span><span style="color:#6F42C1">b</span><span style="color:#24292E">.</span><span style="color:#6F42C1">did_ftplugin_php_after</span><span style="color:#D73A49"> then</span></span> +<span class="line"><span style="color:#D73A49"> return</span></span> +<span class="line"><span style="color:#D73A49">end</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6A737D">-- ここに実際の処理を書く</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">vim.</span><span style="color:#6F42C1">b</span><span style="color:#24292E">.</span><span style="color:#6F42C1">did_ftplugin_php_after</span><span style="color:#D73A49"> =</span><span style="color:#005CC5"> true</span></span></code></pre> + </div> </section> <section id="section--implement"> @@ -159,119 +164,121 @@ vim.b.did_ftplugin_php_after = <span class="hljs-literal">true</span></code></pr 実装を簡単にするため、Composer を用いない場合や PSR 4 以外のオートロード規則を使う場合には対応しない。少々長くなるが、以下にスクリプト全文を載せる。 </p> - <pre class="highlight" language="lua"><code class="highlight"><span class="hljs-keyword">if</span> vim.b.did_ftplugin_php_after <span class="hljs-keyword">then</span> - <span class="hljs-keyword">return</span> -<span class="hljs-keyword">end</span> - -<span class="hljs-comment">-- base_dir を起点としてディレクトリを上向きに辿っていき、composer.json を探す</span> -<span class="hljs-comment">-- :help vim.fs.find()</span> -<span class="hljs-keyword">local</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">find_composer_json</span><span class="hljs-params">(base_dir)</span></span> - <span class="hljs-keyword">return</span> vim.fs.<span class="hljs-built_in">find</span>(<span class="hljs-string">'composer.json'</span>, { - <span class="hljs-built_in">path</span> = base_dir, - upward = <span class="hljs-literal">true</span>, - <span class="hljs-comment">-- ホームディレクトリまで到達したら探索を打ち切る</span> - stop = vim.loop.os_homedir(), - <span class="hljs-built_in">type</span> = <span class="hljs-string">'file'</span>, - })[<span class="hljs-number">1</span>] -<span class="hljs-keyword">end</span> - -<span class="hljs-comment">-- JSON ファイルを読み込み、デコードして返す</span> -<span class="hljs-comment">-- :help readblob()</span> -<span class="hljs-comment">-- :help vim.json.decode</span> -<span class="hljs-comment">-- :help luaref-pcall()</span> -<span class="hljs-keyword">local</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">load_json</span><span class="hljs-params">(file_path)</span></span> - <span class="hljs-comment">-- readblob() は Vim script では Blob オブジェクトを返すが、Lua から呼ぶと string に変換される</span> - <span class="hljs-keyword">local</span> ok_read, content = <span class="hljs-built_in">pcall</span>(vim.fn.readblob, file_path) - <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> ok_read <span class="hljs-keyword">then</span> - <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span> - <span class="hljs-keyword">end</span> - <span class="hljs-keyword">local</span> ok_decode, obj = <span class="hljs-built_in">pcall</span>(vim.json.decode, content) - <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> ok_decode <span class="hljs-keyword">then</span> - <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span> - <span class="hljs-keyword">end</span> - <span class="hljs-keyword">return</span> obj -<span class="hljs-keyword">end</span> - -<span class="hljs-comment">-- 対象ファイルの置かれたディレクトリを基に namespace 宣言を生成する</span> -<span class="hljs-comment">-- :help nvim_buf_get_name()</span> -<span class="hljs-comment">-- :help vim.fs.dirname()</span> -<span class="hljs-keyword">local</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">generate_namespace_declaration</span><span class="hljs-params">()</span></span> - <span class="hljs-comment">-- composer.json を探し、トップレベルの名前空間とディレクトリを特定する</span> - <span class="hljs-keyword">local</span> current_dir = vim.fs.dirname(vim.api.nvim_buf_get_name(<span class="hljs-number">0</span>)) - <span class="hljs-keyword">local</span> path_to_composer_json = find_composer_json(current_dir) - <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> path_to_composer_json <span class="hljs-keyword">then</span> - <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span> <span class="hljs-comment">-- failed to locate composer.json</span> - <span class="hljs-keyword">end</span> - <span class="hljs-keyword">local</span> composer_json = load_json(path_to_composer_json) - <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> composer_json <span class="hljs-keyword">then</span> - <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span> <span class="hljs-comment">-- failed to load composer.json</span> - <span class="hljs-keyword">end</span> - <span class="hljs-comment">-- autoload.psr-4 を探し、型が期待される型と一致するかどうか調べる</span> - <span class="hljs-keyword">local</span> psr4 = vim.tbl_get(composer_json, <span class="hljs-string">'autoload'</span>, <span class="hljs-string">'psr-4'</span>) - <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> psr4 <span class="hljs-keyword">then</span> - <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span> <span class="hljs-comment">-- autoload.psr-4 section is absent</span> - <span class="hljs-keyword">end</span> - <span class="hljs-keyword">if</span> vim.tbl_count(psr4) ~= <span class="hljs-number">1</span> <span class="hljs-keyword">then</span> - <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span> <span class="hljs-comment">-- psr-4 section is ambiguous</span> - <span class="hljs-keyword">end</span> - <span class="hljs-keyword">local</span> psr4_namespace, psr4_dir - <span class="hljs-keyword">for</span> k, v <span class="hljs-keyword">in</span> <span class="hljs-built_in">pairs</span>(psr4) <span class="hljs-keyword">do</span> - psr4_namespace = k - psr4_dir = v - <span class="hljs-keyword">end</span> - <span class="hljs-keyword">if</span> <span class="hljs-built_in">type</span>(psr4_dir) == <span class="hljs-string">'table'</span> <span class="hljs-keyword">then</span> - <span class="hljs-keyword">if</span> #psr4_dir == <span class="hljs-number">1</span> <span class="hljs-keyword">then</span> - psr4_dir = psr4_dir[<span class="hljs-number">1</span>] - <span class="hljs-keyword">else</span> - <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span> <span class="hljs-comment">-- psr-4 section is ambiguous</span> - <span class="hljs-keyword">end</span> - <span class="hljs-keyword">end</span> - <span class="hljs-keyword">if</span> <span class="hljs-built_in">type</span>(psr4_namespace) ~= <span class="hljs-string">'string'</span> <span class="hljs-keyword">or</span> <span class="hljs-built_in">type</span>(psr4_dir) ~= <span class="hljs-string">'string'</span> <span class="hljs-keyword">then</span> - <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span> <span class="hljs-comment">-- psr-4 section is invalid</span> - <span class="hljs-keyword">end</span> - <span class="hljs-comment">-- 末尾のスラッシュとバックスラッシュを取り除いておく</span> - <span class="hljs-keyword">if</span> psr4_namespace:<span class="hljs-built_in">sub</span>(<span class="hljs-number">-1</span>, <span class="hljs-number">-1</span>) == <span class="hljs-string">'\\'</span> <span class="hljs-keyword">then</span> - psr4_namespace = psr4_namespace:<span class="hljs-built_in">sub</span>(<span class="hljs-number">0</span>, <span class="hljs-number">-2</span>) - <span class="hljs-keyword">end</span> - <span class="hljs-keyword">if</span> psr4_dir:<span class="hljs-built_in">sub</span>(<span class="hljs-number">-1</span>, <span class="hljs-number">-1</span>) == <span class="hljs-string">'/'</span> <span class="hljs-keyword">then</span> - psr4_dir = psr4_dir:<span class="hljs-built_in">sub</span>(<span class="hljs-number">0</span>, <span class="hljs-number">-2</span>) - <span class="hljs-keyword">end</span> - - <span class="hljs-comment">-- 対象ファイルが置かれたディレクトリとトップレベルのディレクトリを比較し、その差分を名前空間とする</span> - <span class="hljs-keyword">local</span> namespace_root_dir = vim.fs.dirname(path_to_composer_json) .. <span class="hljs-string">'/'</span> .. psr4_dir - <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> vim.startswith(current_dir, namespace_root_dir) <span class="hljs-keyword">then</span> - <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span> - <span class="hljs-keyword">end</span> - <span class="hljs-keyword">local</span> current_path_suffix = current_dir:<span class="hljs-built_in">sub</span>(#namespace_root_dir + <span class="hljs-number">1</span>) - <span class="hljs-keyword">local</span> namespace = psr4_namespace .. current_path_suffix:<span class="hljs-built_in">gsub</span>(<span class="hljs-string">'/'</span>, <span class="hljs-string">'\\'</span>) - <span class="hljs-keyword">return</span> (<span class="hljs-string">"namespace %s;"</span>):<span class="hljs-built_in">format</span>(namespace) -<span class="hljs-keyword">end</span> - -<span class="hljs-keyword">local</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">generate_template</span><span class="hljs-params">()</span></span> - <span class="hljs-keyword">local</span> <span class="hljs-built_in">lines</span> = { - <span class="hljs-string">'<?php'</span>, - <span class="hljs-string">''</span>, - <span class="hljs-string">'declare(strict_types=1);'</span>, - <span class="hljs-string">''</span>, - } - <span class="hljs-keyword">local</span> namespace_decl = generate_namespace_declaration() - <span class="hljs-keyword">if</span> namespace_decl <span class="hljs-keyword">then</span> - <span class="hljs-built_in">lines</span>[#<span class="hljs-built_in">lines</span> + <span class="hljs-number">1</span>] = namespace_decl - <span class="hljs-built_in">lines</span>[#<span class="hljs-built_in">lines</span> + <span class="hljs-number">1</span>] = <span class="hljs-string">''</span> - <span class="hljs-keyword">end</span> - <span class="hljs-built_in">lines</span>[#<span class="hljs-built_in">lines</span> + <span class="hljs-number">1</span>] = <span class="hljs-string">''</span> - <span class="hljs-keyword">return</span> <span class="hljs-built_in">lines</span> -<span class="hljs-keyword">end</span> - -<span class="hljs-keyword">if</span> vim.fn.line(<span class="hljs-string">'$'</span>) == <span class="hljs-number">1</span> <span class="hljs-keyword">and</span> vim.fn.getline(<span class="hljs-number">1</span>) == <span class="hljs-string">''</span> <span class="hljs-keyword">then</span> - <span class="hljs-comment">-- 対象ファイルが空なら、テンプレートを挿入してカーソルを末尾に移動させる</span> - <span class="hljs-comment">-- :help setline()</span> - <span class="hljs-comment">-- :help cursor()</span> - vim.fn.setline(<span class="hljs-number">1</span>, generate_template()) - vim.fn.cursor(<span class="hljs-string">'$'</span>, <span class="hljs-number">0</span>) -<span class="hljs-keyword">end</span> - -vim.b.did_ftplugin_php_after = <span class="hljs-literal">true</span></code></pre> + <div class="codeblock" language="lua"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">if</span><span style="color:#24292E"> vim.</span><span style="color:#6F42C1">b</span><span style="color:#24292E">.</span><span style="color:#6F42C1">did_ftplugin_php_after</span><span style="color:#D73A49"> then</span></span> +<span class="line"><span style="color:#D73A49"> return</span></span> +<span class="line"><span style="color:#D73A49">end</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6A737D">-- base_dir を起点としてディレクトリを上向きに辿っていき、composer.json を探す</span></span> +<span class="line"><span style="color:#6A737D">-- :help vim.fs.find()</span></span> +<span class="line"><span style="color:#D73A49">local</span><span style="color:#D73A49"> function</span><span style="color:#6F42C1"> find_composer_json</span><span style="color:#24292E">(base_dir)</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#24292E"> vim.</span><span style="color:#6F42C1">fs</span><span style="color:#24292E">.</span><span style="color:#005CC5">find</span><span style="color:#24292E">(</span><span style="color:#032F62">'composer.json'</span><span style="color:#24292E">, {</span></span> +<span class="line"><span style="color:#24292E"> path </span><span style="color:#D73A49">=</span><span style="color:#24292E"> base_dir,</span></span> +<span class="line"><span style="color:#24292E"> upward </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> true</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#6A737D"> -- ホームディレクトリまで到達したら探索を打ち切る</span></span> +<span class="line"><span style="color:#24292E"> stop </span><span style="color:#D73A49">=</span><span style="color:#24292E"> vim.</span><span style="color:#6F42C1">loop</span><span style="color:#24292E">.</span><span style="color:#005CC5">os_homedir</span><span style="color:#24292E">(),</span></span> +<span class="line"><span style="color:#24292E"> type </span><span style="color:#D73A49">=</span><span style="color:#032F62"> 'file'</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E"> })[</span><span style="color:#005CC5">1</span><span style="color:#24292E">]</span></span> +<span class="line"><span style="color:#D73A49">end</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6A737D">-- JSON ファイルを読み込み、デコードして返す</span></span> +<span class="line"><span style="color:#6A737D">-- :help readblob()</span></span> +<span class="line"><span style="color:#6A737D">-- :help vim.json.decode</span></span> +<span class="line"><span style="color:#6A737D">-- :help luaref-pcall()</span></span> +<span class="line"><span style="color:#D73A49">local</span><span style="color:#D73A49"> function</span><span style="color:#6F42C1"> load_json</span><span style="color:#24292E">(file_path)</span></span> +<span class="line"><span style="color:#6A737D"> -- readblob() は Vim script では Blob オブジェクトを返すが、Lua から呼ぶと string に変換される</span></span> +<span class="line"><span style="color:#D73A49"> local</span><span style="color:#24292E"> ok_read, content </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> pcall</span><span style="color:#24292E">(vim.</span><span style="color:#6F42C1">fn</span><span style="color:#24292E">.</span><span style="color:#6F42C1">readblob</span><span style="color:#24292E">, file_path)</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#D73A49"> not</span><span style="color:#24292E"> ok_read </span><span style="color:#D73A49">then</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#005CC5"> nil</span></span> +<span class="line"><span style="color:#D73A49"> end</span></span> +<span class="line"><span style="color:#D73A49"> local</span><span style="color:#24292E"> ok_decode, obj </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> pcall</span><span style="color:#24292E">(vim.</span><span style="color:#6F42C1">json</span><span style="color:#24292E">.</span><span style="color:#6F42C1">decode</span><span style="color:#24292E">, content)</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#D73A49"> not</span><span style="color:#24292E"> ok_decode </span><span style="color:#D73A49">then</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#005CC5"> nil</span></span> +<span class="line"><span style="color:#D73A49"> end</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#24292E"> obj</span></span> +<span class="line"><span style="color:#D73A49">end</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6A737D">-- 対象ファイルの置かれたディレクトリを基に namespace 宣言を生成する</span></span> +<span class="line"><span style="color:#6A737D">-- :help nvim_buf_get_name()</span></span> +<span class="line"><span style="color:#6A737D">-- :help vim.fs.dirname()</span></span> +<span class="line"><span style="color:#D73A49">local</span><span style="color:#D73A49"> function</span><span style="color:#6F42C1"> generate_namespace_declaration</span><span style="color:#24292E">()</span></span> +<span class="line"><span style="color:#6A737D"> -- composer.json を探し、トップレベルの名前空間とディレクトリを特定する</span></span> +<span class="line"><span style="color:#D73A49"> local</span><span style="color:#24292E"> current_dir </span><span style="color:#D73A49">=</span><span style="color:#24292E"> vim.</span><span style="color:#6F42C1">fs</span><span style="color:#24292E">.</span><span style="color:#005CC5">dirname</span><span style="color:#24292E">(vim.</span><span style="color:#6F42C1">api</span><span style="color:#24292E">.</span><span style="color:#005CC5">nvim_buf_get_name</span><span style="color:#24292E">(</span><span style="color:#005CC5">0</span><span style="color:#24292E">))</span></span> +<span class="line"><span style="color:#D73A49"> local</span><span style="color:#24292E"> path_to_composer_json </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> find_composer_json</span><span style="color:#24292E">(current_dir)</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#D73A49"> not</span><span style="color:#24292E"> path_to_composer_json </span><span style="color:#D73A49">then</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#005CC5"> nil</span><span style="color:#6A737D"> -- failed to locate composer.json</span></span> +<span class="line"><span style="color:#D73A49"> end</span></span> +<span class="line"><span style="color:#D73A49"> local</span><span style="color:#24292E"> composer_json </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> load_json</span><span style="color:#24292E">(path_to_composer_json)</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#D73A49"> not</span><span style="color:#24292E"> composer_json </span><span style="color:#D73A49">then</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#005CC5"> nil</span><span style="color:#6A737D"> -- failed to load composer.json</span></span> +<span class="line"><span style="color:#D73A49"> end</span></span> +<span class="line"><span style="color:#6A737D"> -- autoload.psr-4 を探し、型が期待される型と一致するかどうか調べる</span></span> +<span class="line"><span style="color:#D73A49"> local</span><span style="color:#24292E"> psr4 </span><span style="color:#D73A49">=</span><span style="color:#24292E"> vim.</span><span style="color:#005CC5">tbl_get</span><span style="color:#24292E">(composer_json, </span><span style="color:#032F62">'autoload'</span><span style="color:#24292E">, </span><span style="color:#032F62">'psr-4'</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#D73A49"> not</span><span style="color:#24292E"> psr4 </span><span style="color:#D73A49">then</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#005CC5"> nil</span><span style="color:#6A737D"> -- autoload.psr-4 section is absent</span></span> +<span class="line"><span style="color:#D73A49"> end</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> vim.</span><span style="color:#005CC5">tbl_count</span><span style="color:#24292E">(psr4) </span><span style="color:#D73A49">~=</span><span style="color:#005CC5"> 1</span><span style="color:#D73A49"> then</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#005CC5"> nil</span><span style="color:#6A737D"> -- psr-4 section is ambiguous</span></span> +<span class="line"><span style="color:#D73A49"> end</span></span> +<span class="line"><span style="color:#D73A49"> local</span><span style="color:#24292E"> psr4_namespace, psr4_dir</span></span> +<span class="line"><span style="color:#D73A49"> for</span><span style="color:#24292E"> k, v </span><span style="color:#D73A49">in</span><span style="color:#005CC5"> pairs</span><span style="color:#24292E">(psr4) </span><span style="color:#D73A49">do</span></span> +<span class="line"><span style="color:#24292E"> psr4_namespace </span><span style="color:#D73A49">=</span><span style="color:#24292E"> k</span></span> +<span class="line"><span style="color:#24292E"> psr4_dir </span><span style="color:#D73A49">=</span><span style="color:#24292E"> v</span></span> +<span class="line"><span style="color:#D73A49"> end</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#005CC5"> type</span><span style="color:#24292E">(psr4_dir) </span><span style="color:#D73A49">==</span><span style="color:#032F62"> 'table' </span><span style="color:#D73A49">then</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#D73A49"> #</span><span style="color:#24292E">psr4_dir </span><span style="color:#D73A49">==</span><span style="color:#005CC5"> 1</span><span style="color:#D73A49"> then</span></span> +<span class="line"><span style="color:#24292E"> psr4_dir </span><span style="color:#D73A49">=</span><span style="color:#24292E"> psr4_dir[</span><span style="color:#005CC5">1</span><span style="color:#24292E">]</span></span> +<span class="line"><span style="color:#D73A49"> else</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#005CC5"> nil</span><span style="color:#6A737D"> -- psr-4 section is ambiguous</span></span> +<span class="line"><span style="color:#D73A49"> end</span></span> +<span class="line"><span style="color:#D73A49"> end</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#005CC5"> type</span><span style="color:#24292E">(psr4_namespace) </span><span style="color:#D73A49">~=</span><span style="color:#032F62"> 'string' </span><span style="color:#D73A49">or</span><span style="color:#005CC5"> type</span><span style="color:#24292E">(psr4_dir) </span><span style="color:#D73A49">~=</span><span style="color:#032F62"> 'string' </span><span style="color:#D73A49">then</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#005CC5"> nil</span><span style="color:#6A737D"> -- psr-4 section is invalid</span></span> +<span class="line"><span style="color:#D73A49"> end</span></span> +<span class="line"><span style="color:#6A737D"> -- 末尾のスラッシュとバックスラッシュを取り除いておく</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#6F42C1"> psr4_namespace</span><span style="color:#24292E">:</span><span style="color:#005CC5">sub</span><span style="color:#24292E">(</span><span style="color:#D73A49">-</span><span style="color:#005CC5">1</span><span style="color:#24292E">, </span><span style="color:#D73A49">-</span><span style="color:#005CC5">1</span><span style="color:#24292E">) </span><span style="color:#D73A49">==</span><span style="color:#032F62"> '</span><span style="color:#005CC5">\\</span><span style="color:#032F62">' </span><span style="color:#D73A49">then</span></span> +<span class="line"><span style="color:#24292E"> psr4_namespace </span><span style="color:#D73A49">=</span><span style="color:#6F42C1"> psr4_namespace</span><span style="color:#24292E">:</span><span style="color:#005CC5">sub</span><span style="color:#24292E">(</span><span style="color:#005CC5">0</span><span style="color:#24292E">, </span><span style="color:#D73A49">-</span><span style="color:#005CC5">2</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#D73A49"> end</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#6F42C1"> psr4_dir</span><span style="color:#24292E">:</span><span style="color:#005CC5">sub</span><span style="color:#24292E">(</span><span style="color:#D73A49">-</span><span style="color:#005CC5">1</span><span style="color:#24292E">, </span><span style="color:#D73A49">-</span><span style="color:#005CC5">1</span><span style="color:#24292E">) </span><span style="color:#D73A49">==</span><span style="color:#032F62"> '/' </span><span style="color:#D73A49">then</span></span> +<span class="line"><span style="color:#24292E"> psr4_dir </span><span style="color:#D73A49">=</span><span style="color:#6F42C1"> psr4_dir</span><span style="color:#24292E">:</span><span style="color:#005CC5">sub</span><span style="color:#24292E">(</span><span style="color:#005CC5">0</span><span style="color:#24292E">, </span><span style="color:#D73A49">-</span><span style="color:#005CC5">2</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#D73A49"> end</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6A737D"> -- 対象ファイルが置かれたディレクトリとトップレベルのディレクトリを比較し、その差分を名前空間とする</span></span> +<span class="line"><span style="color:#D73A49"> local</span><span style="color:#24292E"> namespace_root_dir </span><span style="color:#D73A49">=</span><span style="color:#24292E"> vim.</span><span style="color:#6F42C1">fs</span><span style="color:#24292E">.</span><span style="color:#005CC5">dirname</span><span style="color:#24292E">(path_to_composer_json) </span><span style="color:#D73A49">..</span><span style="color:#032F62"> '/' </span><span style="color:#D73A49">..</span><span style="color:#24292E"> psr4_dir</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#D73A49"> not</span><span style="color:#24292E"> vim.</span><span style="color:#005CC5">startswith</span><span style="color:#24292E">(current_dir, namespace_root_dir) </span><span style="color:#D73A49">then</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#005CC5"> nil</span></span> +<span class="line"><span style="color:#D73A49"> end</span></span> +<span class="line"><span style="color:#D73A49"> local</span><span style="color:#24292E"> current_path_suffix </span><span style="color:#D73A49">=</span><span style="color:#6F42C1"> current_dir</span><span style="color:#24292E">:</span><span style="color:#005CC5">sub</span><span style="color:#24292E">(</span><span style="color:#D73A49">#</span><span style="color:#24292E">namespace_root_dir </span><span style="color:#D73A49">+</span><span style="color:#005CC5"> 1</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#D73A49"> local</span><span style="color:#24292E"> namespace </span><span style="color:#D73A49">=</span><span style="color:#24292E"> psr4_namespace </span><span style="color:#D73A49">..</span><span style="color:#6F42C1"> current_path_suffix</span><span style="color:#24292E">:</span><span style="color:#005CC5">gsub</span><span style="color:#24292E">(</span><span style="color:#032F62">'/'</span><span style="color:#24292E">, </span><span style="color:#032F62">'</span><span style="color:#005CC5">\\</span><span style="color:#032F62">'</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#24292E"> (</span><span style="color:#032F62">"namespace %s;"</span><span style="color:#24292E">):</span><span style="color:#005CC5">format</span><span style="color:#24292E">(namespace)</span></span> +<span class="line"><span style="color:#D73A49">end</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">local</span><span style="color:#D73A49"> function</span><span style="color:#6F42C1"> generate_template</span><span style="color:#24292E">()</span></span> +<span class="line"><span style="color:#D73A49"> local</span><span style="color:#24292E"> lines </span><span style="color:#D73A49">=</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#032F62"> '<?php'</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#032F62"> ''</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#032F62"> 'declare(strict_types=1);'</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#032F62"> ''</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#D73A49"> local</span><span style="color:#24292E"> namespace_decl </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> generate_namespace_declaration</span><span style="color:#24292E">()</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> namespace_decl </span><span style="color:#D73A49">then</span></span> +<span class="line"><span style="color:#24292E"> lines[</span><span style="color:#D73A49">#</span><span style="color:#24292E">lines </span><span style="color:#D73A49">+</span><span style="color:#005CC5"> 1</span><span style="color:#24292E">] </span><span style="color:#D73A49">=</span><span style="color:#24292E"> namespace_decl</span></span> +<span class="line"><span style="color:#24292E"> lines[</span><span style="color:#D73A49">#</span><span style="color:#24292E">lines </span><span style="color:#D73A49">+</span><span style="color:#005CC5"> 1</span><span style="color:#24292E">] </span><span style="color:#D73A49">=</span><span style="color:#032F62"> ''</span></span> +<span class="line"><span style="color:#D73A49"> end</span></span> +<span class="line"><span style="color:#24292E"> lines[</span><span style="color:#D73A49">#</span><span style="color:#24292E">lines </span><span style="color:#D73A49">+</span><span style="color:#005CC5"> 1</span><span style="color:#24292E">] </span><span style="color:#D73A49">=</span><span style="color:#032F62"> ''</span></span> +<span class="line"><span style="color:#D73A49"> return</span><span style="color:#24292E"> lines</span></span> +<span class="line"><span style="color:#D73A49">end</span></span> +<span class="line"></span> +<span class="line"><span style="color:#D73A49">if</span><span style="color:#24292E"> vim.</span><span style="color:#6F42C1">fn</span><span style="color:#24292E">.</span><span style="color:#005CC5">line</span><span style="color:#24292E">(</span><span style="color:#032F62">'$'</span><span style="color:#24292E">) </span><span style="color:#D73A49">==</span><span style="color:#005CC5"> 1</span><span style="color:#D73A49"> and</span><span style="color:#24292E"> vim.</span><span style="color:#6F42C1">fn</span><span style="color:#24292E">.</span><span style="color:#005CC5">getline</span><span style="color:#24292E">(</span><span style="color:#005CC5">1</span><span style="color:#24292E">) </span><span style="color:#D73A49">==</span><span style="color:#032F62"> '' </span><span style="color:#D73A49">then</span></span> +<span class="line"><span style="color:#6A737D"> -- 対象ファイルが空なら、テンプレートを挿入してカーソルを末尾に移動させる</span></span> +<span class="line"><span style="color:#6A737D"> -- :help setline()</span></span> +<span class="line"><span style="color:#6A737D"> -- :help cursor()</span></span> +<span class="line"><span style="color:#24292E"> vim.</span><span style="color:#6F42C1">fn</span><span style="color:#24292E">.</span><span style="color:#005CC5">setline</span><span style="color:#24292E">(</span><span style="color:#005CC5">1</span><span style="color:#24292E">, </span><span style="color:#005CC5">generate_template</span><span style="color:#24292E">())</span></span> +<span class="line"><span style="color:#24292E"> vim.</span><span style="color:#6F42C1">fn</span><span style="color:#24292E">.</span><span style="color:#005CC5">cursor</span><span style="color:#24292E">(</span><span style="color:#032F62">'$'</span><span style="color:#24292E">, </span><span style="color:#005CC5">0</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#D73A49">end</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">vim.</span><span style="color:#6F42C1">b</span><span style="color:#24292E">.</span><span style="color:#6F42C1">did_ftplugin_php_after</span><span style="color:#D73A49"> =</span><span style="color:#005CC5"> true</span></span></code></pre> + </div> </section> <section id="section--outro"> diff --git a/vhosts/blog/public/posts/2024-02-03/install-wireguard-on-personal-server/index.html b/vhosts/blog/public/posts/2024-02-03/install-wireguard-on-personal-server/index.html index 9b8c1815..f7a6f601 100644 --- a/vhosts/blog/public/posts/2024-02-03/install-wireguard-on-personal-server/index.html +++ b/vhosts/blog/public/posts/2024-02-03/install-wireguard-on-personal-server/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>【備忘録】 個人用サーバに WireGuard を導入する|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -99,14 +98,18 @@ まずは個人用サービスをホストしている Ubuntu のサーバに WireGuard をインストールする。 </p> - <pre class="highlight"><code>$ sudo apt install wireguard</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ sudo apt install wireguard</span></span></code></pre> + </div> <p> 次に、WireGuard で使用する鍵を生成する。 </p> - <pre class="highlight"><code>$ wg genkey | sudo tee /etc/wireguard/server.key | wg pubkey | sudo tee /etc/wireguard/server.pub -$ sudo chmod 600 /etc/wireguard/server.{key,pub}</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ wg genkey | sudo tee /etc/wireguard/server.key | wg pubkey | sudo tee /etc/wireguard/server.pub</span></span> +<span class="line"><span>$ sudo chmod 600 /etc/wireguard/server.{key,pub}</span></span></code></pre> + </div> </section> <section id="section--install-wireguard-client"> @@ -115,25 +118,29 @@ $ sudo chmod 600 /etc/wireguard/server.{key,pub}</code></pre> 公式サイトから各 OS 向けのクライアントソフトウェアを入手し、インストールする。次に、設定をおこなう。 </p> - <pre class="highlight" language="ini"><code class="highlight"><span class="hljs-comment"># クライアント 1 の場合</span> -<span class="hljs-section">[Interface]</span> -<span class="hljs-attr">Address</span> = <span class="hljs-number">10.10</span>.<span class="hljs-number">1.2</span>/<span class="hljs-number">32</span> -<span class="hljs-attr">PrivateKey</span> = <クライアント <span class="hljs-number">1</span> の秘密鍵> - -<span class="hljs-section">[Peer]</span> -<span class="hljs-attr">PublicKey</span> = <サーバの公開鍵> -<span class="hljs-attr">AllowedIPs</span> = <サーバの外部 IP アドレス>/<span class="hljs-number">32</span> -<span class="hljs-attr">Endpoint</span> = <サーバの外部 IP アドレス>:<span class="hljs-number">51820</span></code></pre> - - <pre class="highlight" language="ini"><code class="highlight"><span class="hljs-comment"># クライアント 2 の場合</span> -<span class="hljs-section">[Interface]</span> -<span class="hljs-attr">Address</span> = <span class="hljs-number">10.10</span>.<span class="hljs-number">1.3</span>/<span class="hljs-number">32</span> -<span class="hljs-attr">PrivateKey</span> = <クライアント <span class="hljs-number">2</span> の秘密鍵> - -<span class="hljs-section">[Peer]</span> -<span class="hljs-attr">PublicKey</span> = <サーバの公開鍵> -<span class="hljs-attr">AllowedIPs</span> = <サーバの外部 IP アドレス>/<span class="hljs-number">32</span> -<span class="hljs-attr">Endpoint</span> = <サーバの外部 IP アドレス>:<span class="hljs-number">51820</span></code></pre> + <div class="codeblock" language="ini"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D"># クライアント 1 の場合</span></span> +<span class="line"><span style="color:#6F42C1">[Interface]</span></span> +<span class="line"><span style="color:#D73A49">Address</span><span style="color:#24292E"> = 10.10.1.2/32</span></span> +<span class="line"><span style="color:#D73A49">PrivateKey</span><span style="color:#24292E"> = <クライアント 1 の秘密鍵></span></span> +<span class="line"></span> +<span class="line"><span style="color:#6F42C1">[Peer]</span></span> +<span class="line"><span style="color:#D73A49">PublicKey</span><span style="color:#24292E"> = <サーバの公開鍵></span></span> +<span class="line"><span style="color:#D73A49">AllowedIPs</span><span style="color:#24292E"> = <サーバの外部 IP アドレス>/32</span></span> +<span class="line"><span style="color:#D73A49">Endpoint</span><span style="color:#24292E"> = <サーバの外部 IP アドレス>:51820</span></span></code></pre> + </div> + + <div class="codeblock" language="ini"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D"># クライアント 2 の場合</span></span> +<span class="line"><span style="color:#6F42C1">[Interface]</span></span> +<span class="line"><span style="color:#D73A49">Address</span><span style="color:#24292E"> = 10.10.1.3/32</span></span> +<span class="line"><span style="color:#D73A49">PrivateKey</span><span style="color:#24292E"> = <クライアント 2 の秘密鍵></span></span> +<span class="line"></span> +<span class="line"><span style="color:#6F42C1">[Peer]</span></span> +<span class="line"><span style="color:#D73A49">PublicKey</span><span style="color:#24292E"> = <サーバの公開鍵></span></span> +<span class="line"><span style="color:#D73A49">AllowedIPs</span><span style="color:#24292E"> = <サーバの外部 IP アドレス>/32</span></span> +<span class="line"><span style="color:#D73A49">Endpoint</span><span style="color:#24292E"> = <サーバの外部 IP アドレス>:51820</span></span></code></pre> + </div> <p> <code>PrivateKey</code> や <code>PublicKey</code> は鍵ファイルのパスではなく中身を書くことに注意。 @@ -146,28 +153,34 @@ $ sudo chmod 600 /etc/wireguard/server.{key,pub}</code></pre> 一度サーバへ戻り、WireGuard の設定ファイルを書く。 </p> - <pre class="highlight"><code>$ sudo vim /etc/wireguard/wg0.conf</code></pre> - - <pre class="highlight" language="ini"><code class="highlight"><span class="hljs-section">[Interface]</span> -<span class="hljs-attr">Address</span> = <span class="hljs-number">10.10</span>.<span class="hljs-number">1.1</span>/<span class="hljs-number">32</span> -<span class="hljs-attr">SaveConfig</span> = <span class="hljs-literal">true</span> -<span class="hljs-attr">PrivateKey</span> = <サーバの秘密鍵> -<span class="hljs-attr">ListenPort</span> = <span class="hljs-number">51820</span> - -<span class="hljs-section">[Peer]</span> -<span class="hljs-attr">PublicKey</span> = <クライアント <span class="hljs-number">1</span> の公開鍵> -<span class="hljs-attr">AllowedIPs</span> = <span class="hljs-number">10.10</span>.<span class="hljs-number">1.2</span>/<span class="hljs-number">32</span> - -<span class="hljs-section">[Peer]</span> -<span class="hljs-attr">PublicKey</span> = <クライアント <span class="hljs-number">2</span> の公開鍵> -<span class="hljs-attr">AllowedIPs</span> = <span class="hljs-number">10.10</span>.<span class="hljs-number">1.3</span>/<span class="hljs-number">32</span></code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ sudo vim /etc/wireguard/wg0.conf</span></span></code></pre> + </div> + + <div class="codeblock" language="ini"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6F42C1">[Interface]</span></span> +<span class="line"><span style="color:#D73A49">Address</span><span style="color:#24292E"> = 10.10.1.1/32</span></span> +<span class="line"><span style="color:#D73A49">SaveConfig</span><span style="color:#24292E"> = true</span></span> +<span class="line"><span style="color:#D73A49">PrivateKey</span><span style="color:#24292E"> = <サーバの秘密鍵></span></span> +<span class="line"><span style="color:#D73A49">ListenPort</span><span style="color:#24292E"> = 51820</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6F42C1">[Peer]</span></span> +<span class="line"><span style="color:#D73A49">PublicKey</span><span style="color:#24292E"> = <クライアント 1 の公開鍵></span></span> +<span class="line"><span style="color:#D73A49">AllowedIPs</span><span style="color:#24292E"> = 10.10.1.2/32</span></span> +<span class="line"></span> +<span class="line"><span style="color:#6F42C1">[Peer]</span></span> +<span class="line"><span style="color:#D73A49">PublicKey</span><span style="color:#24292E"> = <クライアント 2 の公開鍵></span></span> +<span class="line"><span style="color:#D73A49">AllowedIPs</span><span style="color:#24292E"> = 10.10.1.3/32</span></span></code></pre> + </div> <p> 次に、WireGuard のサービスを起動する。 </p> - <pre class="highlight"><code>$ sudo systemctl enable wg-quick@wg0 -$ sudo systemctl start wg-quick@wg0</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ sudo systemctl enable wg-quick@wg0</span></span> +<span class="line"><span>$ sudo systemctl start wg-quick@wg0</span></span></code></pre> + </div> </section> <section id="section--configure-firewall"> @@ -176,23 +189,29 @@ $ sudo systemctl start wg-quick@wg0</code></pre> 続けてファイアウォールを設定する。まずは WireGuard が使用する UDP のポートを開き、<code>wg0</code> を通る通信を許可する。 </p> - <pre class="highlight"><code>$ sudo ufw allow 51820/udp -$ sudo ufw allow in on wg0 -$ sudo ufw allow out on wg0</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ sudo ufw allow 51820/udp</span></span> +<span class="line"><span>$ sudo ufw allow in on wg0</span></span> +<span class="line"><span>$ sudo ufw allow out on wg0</span></span></code></pre> + </div> <p> 次に、80 や 443 などの必要なポートについて、<code>wg0</code> を経由してのアクセスのみ許可する。 </p> - <pre class="highlight"><code>$ sudo ufw allow in on wg0 to any port 80 proto tcp -$ sudo ufw allow in on wg0 to any port 443 proto tcp</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ sudo ufw allow in on wg0 to any port 80 proto tcp</span></span> +<span class="line"><span>$ sudo ufw allow in on wg0 to any port 443 proto tcp</span></span></code></pre> + </div> <p> 最後に、<code>ufw</code> を有効にする。 </p> - <pre class="highlight"><code>$ sudo ufw status -$ sudo ufw enable</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ sudo ufw status</span></span> +<span class="line"><span>$ sudo ufw enable</span></span></code></pre> + </div> </section> <section id="section--connect-each-other"> diff --git a/vhosts/blog/public/posts/2024-02-10/yapcjapan-2024-report/index.html b/vhosts/blog/public/posts/2024-02-10/yapcjapan-2024-report/index.html index 27f11038..62debe04 100644 --- a/vhosts/blog/public/posts/2024-02-10/yapcjapan-2024-report/index.html +++ b/vhosts/blog/public/posts/2024-02-10/yapcjapan-2024-report/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>YAPC::Hiroshima 2024 参加レポ|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> diff --git a/vhosts/blog/public/posts/2024-02-22/phpkansai-2024-report/index.html b/vhosts/blog/public/posts/2024-02-22/phpkansai-2024-report/index.html index 4cb0c230..e47eef88 100644 --- a/vhosts/blog/public/posts/2024-02-22/phpkansai-2024-report/index.html +++ b/vhosts/blog/public/posts/2024-02-22/phpkansai-2024-report/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>PHPカンファレンス関西 2024 参加レポ|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> diff --git a/vhosts/blog/public/posts/2024-03-17/phperkaigi-2024-report/index.html b/vhosts/blog/public/posts/2024-03-17/phperkaigi-2024-report/index.html index a906374b..80ec045e 100644 --- a/vhosts/blog/public/posts/2024-03-17/phperkaigi-2024-report/index.html +++ b/vhosts/blog/public/posts/2024-03-17/phperkaigi-2024-report/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>PHPerKaigi 2024 参加レポ|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> diff --git a/vhosts/blog/public/posts/2024-03-20/my-bucket-list/index.html b/vhosts/blog/public/posts/2024-03-20/my-bucket-list/index.html index e1449afa..2b874bf3 100644 --- a/vhosts/blog/public/posts/2024-03-20/my-bucket-list/index.html +++ b/vhosts/blog/public/posts/2024-03-20/my-bucket-list/index.html @@ -13,8 +13,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>死ぬまでに作る自作○○一覧あるいは人生の TODO リスト|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> diff --git a/vhosts/blog/public/posts/2024-04-14/phpcon-odawara-2024-report/index.html b/vhosts/blog/public/posts/2024-04-14/phpcon-odawara-2024-report/index.html index 4f7abef8..92983841 100644 --- a/vhosts/blog/public/posts/2024-04-14/phpcon-odawara-2024-report/index.html +++ b/vhosts/blog/public/posts/2024-04-14/phpcon-odawara-2024-report/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>PHP カンファレンス小田原 2024 参加レポ|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> diff --git a/vhosts/blog/public/posts/2024-04-21/pipefail-option-in-gitlab-ci-cd/index.html b/vhosts/blog/public/posts/2024-04-21/pipefail-option-in-gitlab-ci-cd/index.html index bf281982..3e41bbf7 100644 --- a/vhosts/blog/public/posts/2024-04-21/pipefail-option-in-gitlab-ci-cd/index.html +++ b/vhosts/blog/public/posts/2024-04-21/pipefail-option-in-gitlab-ci-cd/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>【GitLab】 GitLab CI/CD 上での bash/sh は pipefail が有効になっている|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -89,14 +88,16 @@ 例: </p> - <pre class="highlight" filename=".gitlab-ci.yml" language="yaml"><code class="highlight"><span class="hljs-attr">hello-world:</span> - <span class="hljs-attr">stage:</span> <span class="hljs-string">test</span> - <span class="hljs-attr">image:</span> <span class="hljs-string">alpine:latest</span> - <span class="hljs-attr">script:</span> - <span class="hljs-bullet">-</span> <span class="hljs-string">'echo "Hello, World!"'</span> - <span class="hljs-attr">rules:</span> - <span class="hljs-bullet">-</span> <span class="hljs-attr">if:</span> <span class="hljs-string">'$CI_MERGE_REQUEST_IID'</span> - <span class="hljs-attr">when:</span> <span class="hljs-string">always</span></code></pre> + <div class="codeblock" filename=".gitlab-ci.yml" language="yaml"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#22863A">hello-world</span><span style="color:#24292E">:</span></span> +<span class="line"><span style="color:#22863A"> stage</span><span style="color:#24292E">: </span><span style="color:#032F62">test</span></span> +<span class="line"><span style="color:#22863A"> image</span><span style="color:#24292E">: </span><span style="color:#032F62">alpine:latest</span></span> +<span class="line"><span style="color:#22863A"> script</span><span style="color:#24292E">:</span></span> +<span class="line"><span style="color:#24292E"> - </span><span style="color:#032F62">'echo "Hello, World!"'</span></span> +<span class="line"><span style="color:#22863A"> rules</span><span style="color:#24292E">:</span></span> +<span class="line"><span style="color:#24292E"> - </span><span style="color:#22863A">if</span><span style="color:#24292E">: </span><span style="color:#032F62">'$CI_MERGE_REQUEST_IID'</span></span> +<span class="line"><span style="color:#22863A"> when</span><span style="color:#24292E">: </span><span style="color:#032F62">always</span></span></code></pre> + </div> <p> ここで、<code>script</code> に指定したコマンドが失敗する (exit status が 0 以外になる) と、即座に実行が停止され、ジョブは失敗する。 @@ -106,14 +107,16 @@ では、次のようなケースだとどうなるか。 </p> - <pre class="highlight" filename=".gitlab-ci.yml" language="yaml"><code class="highlight"><span class="hljs-attr">hello-world:</span> - <span class="hljs-attr">stage:</span> <span class="hljs-string">test</span> - <span class="hljs-attr">image:</span> <span class="hljs-string">alpine:latest</span> - <span class="hljs-attr">script:</span> - <span class="hljs-bullet">-</span> <span class="hljs-string">'exit 1 | exit 0'</span> - <span class="hljs-attr">rules:</span> - <span class="hljs-bullet">-</span> <span class="hljs-attr">if:</span> <span class="hljs-string">'$CI_MERGE_REQUEST_IID'</span> - <span class="hljs-attr">when:</span> <span class="hljs-string">always</span></code></pre> + <div class="codeblock" filename=".gitlab-ci.yml" language="yaml"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#22863A">hello-world</span><span style="color:#24292E">:</span></span> +<span class="line"><span style="color:#22863A"> stage</span><span style="color:#24292E">: </span><span style="color:#032F62">test</span></span> +<span class="line"><span style="color:#22863A"> image</span><span style="color:#24292E">: </span><span style="color:#032F62">alpine:latest</span></span> +<span class="line"><span style="color:#22863A"> script</span><span style="color:#24292E">:</span></span> +<span class="line"><span style="color:#24292E"> - </span><span style="color:#032F62">'exit 1 | exit 0'</span></span> +<span class="line"><span style="color:#22863A"> rules</span><span style="color:#24292E">:</span></span> +<span class="line"><span style="color:#24292E"> - </span><span style="color:#22863A">if</span><span style="color:#24292E">: </span><span style="color:#032F62">'$CI_MERGE_REQUEST_IID'</span></span> +<span class="line"><span style="color:#22863A"> when</span><span style="color:#24292E">: </span><span style="color:#032F62">always</span></span></code></pre> + </div> <p> 失敗するコマンドをパイプに接続した。通常 Bash では、パイプの最後のコマンドの exit code が全体の exit code になる。 @@ -126,10 +129,12 @@ 前述したようなケースにおいて、途中で失敗したときに全体を失敗させるには、<code>pipefail</code> オプションを有効にする。 </p> - <pre class="highlight" language="bash"><code class="highlight"><span class="hljs-comment"># On にする</span> -<span class="hljs-built_in">set</span> -o pipefail -<span class="hljs-comment"># Off にする</span> -<span class="hljs-built_in">set</span> +o pipefail</code></pre> + <div class="codeblock" language="bash"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D"># On にする</span></span> +<span class="line"><span style="color:#005CC5">set</span><span style="color:#005CC5"> -o</span><span style="color:#032F62"> pipefail</span></span> +<span class="line"><span style="color:#6A737D"># Off にする</span></span> +<span class="line"><span style="color:#005CC5">set</span><span style="color:#032F62"> +o</span><span style="color:#032F62"> pipefail</span></span></code></pre> + </div> <p> こうすると、パイプ全体が失敗するようになる。この設定は、デフォルトだと off になっている。 @@ -143,14 +148,16 @@ 次のような GitLab CI/CD ジョブが失敗してしまった。 </p> - <pre class="highlight" filename=".gitlab-ci.yml" language="yaml"><code class="highlight"><span class="hljs-attr">hoge:</span> - <span class="hljs-attr">stage:</span> <span class="hljs-string">test</span> - <span class="hljs-attr">image:</span> <span class="hljs-string">alpine:latest</span> - <span class="hljs-attr">script:</span> - <span class="hljs-bullet">-</span> <span class="hljs-string">'cat hoge.txt | grep piyo | sed -e "s/foo/bar/g"'</span> - <span class="hljs-attr">rules:</span> - <span class="hljs-bullet">-</span> <span class="hljs-attr">if:</span> <span class="hljs-string">'$CI_MERGE_REQUEST_IID'</span> - <span class="hljs-attr">when:</span> <span class="hljs-string">always</span></code></pre> + <div class="codeblock" filename=".gitlab-ci.yml" language="yaml"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#22863A">hoge</span><span style="color:#24292E">:</span></span> +<span class="line"><span style="color:#22863A"> stage</span><span style="color:#24292E">: </span><span style="color:#032F62">test</span></span> +<span class="line"><span style="color:#22863A"> image</span><span style="color:#24292E">: </span><span style="color:#032F62">alpine:latest</span></span> +<span class="line"><span style="color:#22863A"> script</span><span style="color:#24292E">:</span></span> +<span class="line"><span style="color:#24292E"> - </span><span style="color:#032F62">'cat hoge.txt | grep piyo | sed -e "s/foo/bar/g"'</span></span> +<span class="line"><span style="color:#22863A"> rules</span><span style="color:#24292E">:</span></span> +<span class="line"><span style="color:#24292E"> - </span><span style="color:#22863A">if</span><span style="color:#24292E">: </span><span style="color:#032F62">'$CI_MERGE_REQUEST_IID'</span></span> +<span class="line"><span style="color:#22863A"> when</span><span style="color:#24292E">: </span><span style="color:#032F62">always</span></span></code></pre> + </div> <p> <code>grep</code> コマンドは、パターンにマッチする行が一行もなかったとき、exit code 1 を返す。よって、<code>pipefail</code> が on になっていると、このジョブは失敗する。現在の <code>pipefail</code> がどうなっているか確かめるため <code>set +o</code> で全オプションを出力させたところ、<code>pipefail</code> が on になっていた。 @@ -160,20 +167,22 @@ しかし、先述したように Bash における <code>pipefail</code> のデフォルト値は off のはずだ。実際に、ローカルで <code>alpine:latest</code> を動かしてみたところ、 </p> - <pre class="highlight"><code>$ docker run --rm alpine:latest sh -c "set +o" -set +o errexit -set +o noglob -set +o ignoreeof -set +o monitor -set +o noexec -set +o xtrace -set +o verbose -set +o noclobber -set +o allexport -set +o notify -set +o nounset -set +o vi -set +o pipefail</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ docker run --rm alpine:latest sh -c "set +o"</span></span> +<span class="line"><span>set +o errexit</span></span> +<span class="line"><span>set +o noglob</span></span> +<span class="line"><span>set +o ignoreeof</span></span> +<span class="line"><span>set +o monitor</span></span> +<span class="line"><span>set +o noexec</span></span> +<span class="line"><span>set +o xtrace</span></span> +<span class="line"><span>set +o verbose</span></span> +<span class="line"><span>set +o noclobber</span></span> +<span class="line"><span>set +o allexport</span></span> +<span class="line"><span>set +o notify</span></span> +<span class="line"><span>set +o nounset</span></span> +<span class="line"><span>set +o vi</span></span> +<span class="line"><span>set +o pipefail</span></span></code></pre> + </div> <p> 確かに <code>pipefail</code> は無効になっている。 @@ -190,9 +199,11 @@ set +o pipefail</code></pre> <code>.gitlab-ci.yml</code> で明示的には書いていないので、GitLab Runner (GitLab CI/CD のスクリプトを実行するプログラム) が勝手に追加しているに違いない。そう仮説を立てて <a href="https://gitlab.com/gitlab-org/gitlab-runner" rel="noreferrer" target="_blank">GitLab Runner のリポジトリ</a> を調査したところ、<a href="https://gitlab.com/gitlab-org/gitlab-runner/-/blob/c75da0796a0e3048991dccfdf2784e3d931beda4/shells/bash.go#L276" rel="noreferrer" target="_blank">ソースコード中の以下の箇所</a> で <code>set -o pipefail</code> していることが判明した (コメントは筆者による)。 </p> - <pre class="highlight" language="go"><code class="highlight"><span class="hljs-comment">// pipefail オプションが存在しない環境にも対応するため、</span> -<span class="hljs-comment">// 先に set -o でオプション一覧を表示させたあと、set -o pipefail している</span> -buf.WriteString(<span class="hljs-string">"if set -o | grep pipefail > /dev/null; then set -o pipefail; fi; set -o errexit\n"</span>)</code></pre> + <div class="codeblock" language="go"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D">// pipefail オプションが存在しない環境にも対応するため、</span></span> +<span class="line"><span style="color:#6A737D">// 先に set -o でオプション一覧を表示させたあと、set -o pipefail している</span></span> +<span class="line"><span style="color:#24292E">buf.</span><span style="color:#6F42C1">WriteString</span><span style="color:#24292E">(</span><span style="color:#032F62">"if set -o | grep pipefail > /dev/null; then set -o pipefail; fi; set -o errexit</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">)</span></span></code></pre> + </div> </section> <section id="section--how-to-solve"> @@ -201,16 +212,18 @@ buf.WriteString(<span class="hljs-string">"if set -o | grep pipefail > / 通常の Bash スクリプトを書く場合と同様に、<code>pipefail</code> が on になっていては困る場所だけ off にしてやればよい。 </p> - <pre class="highlight" diff="true" filename=".gitlab-ci.yml" language="yaml"><code class="highlight"> <span class="hljs-attr">hoge:</span> - <span class="hljs-attr">stage:</span> <span class="hljs-string">test</span> - <span class="hljs-attr">image:</span> <span class="hljs-string">alpine:latest</span> - <span class="hljs-attr">script:</span> -<span class="hljs-string">+</span> <span class="hljs-bullet">-</span> <span class="hljs-string">'set +o pipefail'</span> - <span class="hljs-bullet">-</span> <span class="hljs-string">'cat hoge.txt | grep piyo | sed -e "s/foo/bar/g"'</span> -<span class="hljs-string">+</span> <span class="hljs-bullet">-</span> <span class="hljs-string">'set -o pipefail'</span> <span class="hljs-comment"># この例の場合、ここで終わりなので戻さなくてもよい</span> - <span class="hljs-attr">rules:</span> - <span class="hljs-bullet">-</span> <span class="hljs-attr">if:</span> <span class="hljs-string">'$CI_MERGE_REQUEST_IID'</span> - <span class="hljs-attr">when:</span> <span class="hljs-string">always</span></code></pre> + <div class="codeblock" diff="true" filename=".gitlab-ci.yml" language="yaml"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#22863A"> hoge</span><span style="color:#24292E">:</span></span> +<span class="line"><span style="color:#22863A"> stage</span><span style="color:#24292E">: </span><span style="color:#032F62">test</span></span> +<span class="line"><span style="color:#22863A"> image</span><span style="color:#24292E">: </span><span style="color:#032F62">alpine:latest</span></span> +<span class="line"><span style="color:#22863A"> script</span><span style="color:#24292E">:</span></span> +<span class="line"><span style="color:#032F62">+ - 'set +o pipefail'</span></span> +<span class="line"><span style="color:#24292E"> - </span><span style="color:#032F62">'cat hoge.txt | grep piyo | sed -e "s/foo/bar/g"'</span></span> +<span class="line"><span style="color:#032F62">+ - 'set -o pipefail'</span><span style="color:#6A737D"> # この例の場合、ここで終わりなので戻さなくてもよい</span></span> +<span class="line"><span style="color:#22863A"> rules</span><span style="color:#24292E">:</span></span> +<span class="line"><span style="color:#24292E"> - </span><span style="color:#22863A">if</span><span style="color:#24292E">: </span><span style="color:#032F62">'$CI_MERGE_REQUEST_IID'</span></span> +<span class="line"><span style="color:#22863A"> when</span><span style="color:#24292E">: </span><span style="color:#032F62">always</span></span></code></pre> + </div> </section> <section id="section--remarks"> diff --git a/vhosts/blog/public/posts/2024-04-29/zsh-file-completion-for-composer-custom-commands/index.html b/vhosts/blog/public/posts/2024-04-29/zsh-file-completion-for-composer-custom-commands/index.html index 99216975..c1390ced 100644 --- a/vhosts/blog/public/posts/2024-04-29/zsh-file-completion-for-composer-custom-commands/index.html +++ b/vhosts/blog/public/posts/2024-04-29/zsh-file-completion-for-composer-custom-commands/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>【Zsh】 Composer のカスタムコマンドに対する Zsh 補完で引数にファイルを補完させる|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -98,11 +97,13 @@ このことは、先ほどリンクを載せた <code>_composer</code> 関数を定義しているファイルの冒頭にも書かれている。 </p> - <pre class="highlight" language="zsh"><code class="highlight"><span class="hljs-comment"># - @todo We don't complete custom commands (including script aliases). This is</span> -<span class="hljs-comment"># easy to do in the general case, but it probably requires some clever caching</span> -<span class="hljs-comment"># to avoid introducing a noticeable lag to every completion operation, due to</span> -<span class="hljs-comment"># the way command resolution works and the fact that discovering custom</span> -<span class="hljs-comment"># commands requires making slow calls to Composer</span></code></pre> + <div class="codeblock" language="zsh"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D"># - @todo We don't complete custom commands (including script aliases). This is</span></span> +<span class="line"><span style="color:#6A737D"># easy to do in the general case, but it probably requires some clever caching</span></span> +<span class="line"><span style="color:#6A737D"># to avoid introducing a noticeable lag to every completion operation, due to</span></span> +<span class="line"><span style="color:#6A737D"># the way command resolution works and the fact that discovering custom</span></span> +<span class="line"><span style="color:#6A737D"># commands requires making slow calls to Composer</span></span></code></pre> + </div> </section> <section id="section--what-i-want-to-achive"> @@ -122,7 +123,9 @@ まずは、Zsh で補完関数を提供する場合のボイラープレートコードを書く。以下は <code>~/.zshrc</code> にすべて書く前提だが、<code>autoload</code> を設定するなどすれば別ファイルに分離できる (詳細な手順は割愛)。 </p> - <pre class="highlight" language="zsh"><code class="highlight">compdef _my_composer composer composer.phar</code></pre> + <div class="codeblock" language="zsh"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6F42C1">compdef</span><span style="color:#032F62"> _my_composer</span><span style="color:#032F62"> composer</span><span style="color:#032F62"> composer.phar</span></span></code></pre> + </div> <p> <code>compdef</code> は Zsh が用意している関数で、第一引数に補完関数の名前、第二引数以降に補完を適用するコマンド名を並べる。この場合は、<code>composer</code> コマンドや <code>composer.phar</code> コマンドに対して <code>_my_composer</code> を使って補完をおこなうよう定義している。 @@ -132,9 +135,11 @@ 次に <code>_my_composer</code> を定義する。基本的にはデフォルトの <code>composer</code> コマンドの補完関数 (つまり <code>_composer</code> 関数) を使い、それが何も返さなかった場合に限り、Zsh のファイル・ディレクトリ補完へフォールバックする。 </p> - <pre class="highlight" language="zsh"><code class="highlight"><span class="hljs-keyword">function</span> <span class="hljs-function"><span class="hljs-title">_my_composer</span></span>() { - _composer <span class="hljs-string">"<span class="hljs-variable">$@</span>"</span> || _files <span class="hljs-string">"<span class="hljs-variable">$@</span>"</span> -}</code></pre> + <div class="codeblock" language="zsh"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">function</span><span style="color:#6F42C1"> _my_composer</span><span style="color:#24292E">() {</span></span> +<span class="line"><span style="color:#6F42C1"> _composer</span><span style="color:#032F62"> "</span><span style="color:#005CC5">$@</span><span style="color:#032F62">"</span><span style="color:#D73A49"> ||</span><span style="color:#6F42C1"> _files</span><span style="color:#032F62"> "</span><span style="color:#005CC5">$@</span><span style="color:#032F62">"</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> <code>_composer</code> コマンドは何も補完候補がなかったとき非ゼロな exit status で終了するので、そうであったなら <code>_files</code> を呼び出す。<code>_files</code> は、Zsh がデフォルトで用意しているファイル・ディレクトリの補完をおこなう関数である。 diff --git a/vhosts/blog/public/posts/2024-05-11/phpconkagawa-2024-report/index.html b/vhosts/blog/public/posts/2024-05-11/phpconkagawa-2024-report/index.html index e3f53399..1e9634dd 100644 --- a/vhosts/blog/public/posts/2024-05-11/phpconkagawa-2024-report/index.html +++ b/vhosts/blog/public/posts/2024-05-11/phpconkagawa-2024-report/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>PHP カンファレンス香川 2024 参加レポ|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> diff --git a/vhosts/blog/public/posts/2024-06-19/scalamatsuri-2024-report/index.html b/vhosts/blog/public/posts/2024-06-19/scalamatsuri-2024-report/index.html index d5444b32..5e3263bf 100644 --- a/vhosts/blog/public/posts/2024-06-19/scalamatsuri-2024-report/index.html +++ b/vhosts/blog/public/posts/2024-06-19/scalamatsuri-2024-report/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>ScalaMatsuri 2024 参加レポ|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> diff --git a/vhosts/blog/public/posts/2024-07-19/reparojson-fix-only-json-formatter/index.html b/vhosts/blog/public/posts/2024-07-19/reparojson-fix-only-json-formatter/index.html index c5724274..6fb4f0d0 100644 --- a/vhosts/blog/public/posts/2024-07-19/reparojson-fix-only-json-formatter/index.html +++ b/vhosts/blog/public/posts/2024-07-19/reparojson-fix-only-json-formatter/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>reparojson: 文法エラーを直すだけの JSON フォーマッタを作った|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -91,17 +90,19 @@ 次のように動作する。 </p> - <pre class="highlight"><code>$ echo '[ 1 2 ]' | reparojson -[ 1, 2 ] - -$ echo '[ 1, 2, ]' | reparojson -[ 1, 2 ] - -$ echo '{ "foo": 1 "bar": 2 }' | reparojson -{ "foo": 1, "bar": 2 } - -$ echo '{ "foo": 1, "bar": 2, }' | reparojson -{ "foo": 1, "bar": 2 }</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ echo '[ 1 2 ]' | reparojson</span></span> +<span class="line"><span>[ 1, 2 ]</span></span> +<span class="line"><span></span></span> +<span class="line"><span>$ echo '[ 1, 2, ]' | reparojson</span></span> +<span class="line"><span>[ 1, 2 ]</span></span> +<span class="line"><span></span></span> +<span class="line"><span>$ echo '{ "foo": 1 "bar": 2 }' | reparojson</span></span> +<span class="line"><span>{ "foo": 1, "bar": 2 }</span></span> +<span class="line"><span></span></span> +<span class="line"><span>$ echo '{ "foo": 1, "bar": 2, }' | reparojson</span></span> +<span class="line"><span>{ "foo": 1, "bar": 2 }</span></span></code></pre> + </div> <p> バージョン 0.1.1 時点で修正対象の文法エラーは次のとおり: @@ -140,33 +141,35 @@ $ echo '{ "foo": 1, "bar": 2, }' | reparojson ここでは、<a href="https://github.com/neovim/nvim-lspconfig" rel="noreferrer" target="_blank">nvim-lspconfig</a> と <a href="https://github.com/mattn/efm-langserver" rel="noreferrer" target="_blank">efm-langserver</a> を用いた設定例を紹介する。 </p> - <pre class="highlight" language="lua"><code class="highlight"><span class="hljs-keyword">local</span> lspconfig = <span class="hljs-built_in">require</span>(<span class="hljs-string">'lspconfig'</span>) - -lspconfig.efm.setup({ - init_options = { documentFormatting = <span class="hljs-literal">true</span> }, - settings = { - rootMarkers = {<span class="hljs-string">".git/"</span>}, - languages = { - json = { - { - formatCommand = <span class="hljs-string">"reparojson -q"</span>, - formatStdin = <span class="hljs-literal">true</span>, - }, - }, - }, - } -}) - -vim.api.nvim_create_autocmd(<span class="hljs-string">'LspAttach'</span>, { - callback = <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(e)</span></span> - vim.api.nvim_create_autocmd(<span class="hljs-string">'BufWritePre'</span>, { - buffer = e.buf, - callback = <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span> - vim.lsp.buf.<span class="hljs-built_in">format</span>({ async = <span class="hljs-literal">false</span> }) - <span class="hljs-keyword">end</span> - }) - <span class="hljs-keyword">end</span>, -})</code></pre> + <div class="codeblock" language="lua"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">local</span><span style="color:#24292E"> lspconfig </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> require</span><span style="color:#24292E">(</span><span style="color:#032F62">'lspconfig'</span><span style="color:#24292E">)</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">lspconfig.</span><span style="color:#6F42C1">efm</span><span style="color:#24292E">.</span><span style="color:#005CC5">setup</span><span style="color:#24292E">({</span></span> +<span class="line"><span style="color:#24292E"> init_options </span><span style="color:#D73A49">=</span><span style="color:#24292E"> { documentFormatting </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> true</span><span style="color:#24292E"> },</span></span> +<span class="line"><span style="color:#24292E"> settings </span><span style="color:#D73A49">=</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> rootMarkers </span><span style="color:#D73A49">=</span><span style="color:#24292E"> {</span><span style="color:#032F62">".git/"</span><span style="color:#24292E">},</span></span> +<span class="line"><span style="color:#24292E"> languages </span><span style="color:#D73A49">=</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> json </span><span style="color:#D73A49">=</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> formatCommand </span><span style="color:#D73A49">=</span><span style="color:#032F62"> "reparojson -q"</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E"> formatStdin </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> true</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E"> },</span></span> +<span class="line"><span style="color:#24292E"> },</span></span> +<span class="line"><span style="color:#24292E"> },</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E">})</span></span> +<span class="line"></span> +<span class="line"><span style="color:#24292E">vim.</span><span style="color:#6F42C1">api</span><span style="color:#24292E">.</span><span style="color:#005CC5">nvim_create_autocmd</span><span style="color:#24292E">(</span><span style="color:#032F62">'LspAttach'</span><span style="color:#24292E">, {</span></span> +<span class="line"><span style="color:#6F42C1"> callback</span><span style="color:#D73A49"> =</span><span style="color:#D73A49"> function</span><span style="color:#24292E">(e)</span></span> +<span class="line"><span style="color:#24292E"> vim.</span><span style="color:#6F42C1">api</span><span style="color:#24292E">.</span><span style="color:#005CC5">nvim_create_autocmd</span><span style="color:#24292E">(</span><span style="color:#032F62">'BufWritePre'</span><span style="color:#24292E">, {</span></span> +<span class="line"><span style="color:#24292E"> buffer </span><span style="color:#D73A49">=</span><span style="color:#24292E"> e.</span><span style="color:#6F42C1">buf</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#6F42C1"> callback</span><span style="color:#D73A49"> =</span><span style="color:#D73A49"> function</span><span style="color:#24292E">()</span></span> +<span class="line"><span style="color:#24292E"> vim.</span><span style="color:#6F42C1">lsp</span><span style="color:#24292E">.</span><span style="color:#6F42C1">buf</span><span style="color:#24292E">.</span><span style="color:#005CC5">format</span><span style="color:#24292E">({ async </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> false</span><span style="color:#24292E"> })</span></span> +<span class="line"><span style="color:#D73A49"> end</span></span> +<span class="line"><span style="color:#24292E"> })</span></span> +<span class="line"><span style="color:#D73A49"> end</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E">})</span></span></code></pre> + </div> <p> ほとんどは nvim-lspconfig と efm-langserver を使う際のボイラープレートだが、<code>formatCommand</code> で <code>-q</code> フラグを指定していることに注意してほしい。このツールは、デフォルトでは JSON が修正された場合 exit code 1 で終了する。これは、入力が最初から正しかった場合と修正して正しくなった場合を区別するためだが、異常終了してしまうと置き換えが発生しない。そのため、<code>-q</code> フラグを指定して、修正されたときも exit code 0 で終了するようにしている。 @@ -179,28 +182,34 @@ vim.api.nvim_create_autocmd(<span class="hljs-string">'LspAttach'</spa このツールが威力を発揮するのは、行の入れ換え時である。次のような JSON があり、 </p> - <pre class="highlight" language="json"><code class="highlight"><span class="hljs-punctuation">{</span> - <span class="hljs-attr">"a"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span> - <span class="hljs-attr">"b"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span> -<span class="hljs-punctuation">}</span></code></pre> + <div class="codeblock" language="json"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">{</span></span> +<span class="line"><span style="color:#005CC5"> "a"</span><span style="color:#24292E">: </span><span style="color:#005CC5">true</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#005CC5"> "b"</span><span style="color:#24292E">: </span><span style="color:#005CC5">false</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> 2行目と3行目を入れ換えて以下のように編集した。 </p> - <pre class="highlight" language="json"><code class="highlight"><span class="hljs-punctuation">{</span> - <span class="hljs-attr">"b"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span> - <span class="hljs-attr">"a"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span> -<span class="hljs-punctuation">}</span></code></pre> + <div class="codeblock" language="json"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">{</span></span> +<span class="line"><span style="color:#005CC5"> "b"</span><span style="color:#24292E">: </span><span style="color:#005CC5">false</span></span> +<span class="line"><span style="color:#032F62"> "a"</span><span style="color:#B31D28;font-style:italic">:</span><span style="color:#005CC5"> true</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> これは不正な JSON だが、このツールを通せば次のようになる。 </p> - <pre class="highlight" language="json"><code class="highlight"><span class="hljs-punctuation">{</span> - <span class="hljs-attr">"b"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span> - <span class="hljs-attr">"a"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span> -<span class="hljs-punctuation">}</span></code></pre> + <div class="codeblock" language="json"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">{</span></span> +<span class="line"><span style="color:#005CC5"> "b"</span><span style="color:#24292E">: </span><span style="color:#005CC5">false</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#005CC5"> "a"</span><span style="color:#24292E">: </span><span style="color:#005CC5">true</span></span> +<span class="line"><span style="color:#24292E">}</span></span></code></pre> + </div> <p> もちろん、このような操作を文法を壊さずにおこなう Vim プラグインは存在する。しかし、単なる行の入れ換えであれば <code>ddp</code> の3ストロークでおこなうことができ、専用のキーバインドを覚える必要もない。このツールを用いることで、より Vimmer-friendly な JSON 編集が可能となる。 diff --git a/vhosts/blog/public/posts/2024-08-19/go-template-access-outer-scope-pipeline-within-with-or-range/index.html b/vhosts/blog/public/posts/2024-08-19/go-template-access-outer-scope-pipeline-within-with-or-range/index.html index 2d2c3761..aa6d2afb 100644 --- a/vhosts/blog/public/posts/2024-08-19/go-template-access-outer-scope-pipeline-within-with-or-range/index.html +++ b/vhosts/blog/public/posts/2024-08-19/go-template-access-outer-scope-pipeline-within-with-or-range/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>【Go】 text/template の with や range の内側から外側の "." にアクセスする|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -71,19 +70,21 @@ Go には、標準ライブラリにテンプレートライブラリ <code>text/template</code> がある。この <code>text/template</code> における制御構造、<code>with</code> と <code>range</code> は次のように使われる。 </p> - <pre class="highlight"><code># {{ .Title }} - -# User - -{{ with .User }} - {{ .Name }} ({{ .ID }}) -{{ end }} - -# Items - -{{ range .Items }} - - {{ . }} -{{ end }}</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span># {{ .Title }}</span></span> +<span class="line"><span></span></span> +<span class="line"><span># User</span></span> +<span class="line"><span></span></span> +<span class="line"><span>{{ with .User }}</span></span> +<span class="line"><span> {{ .Name }} ({{ .ID }})</span></span> +<span class="line"><span>{{ end }}</span></span> +<span class="line"><span></span></span> +<span class="line"><span># Items</span></span> +<span class="line"><span></span></span> +<span class="line"><span>{{ range .Items }}</span></span> +<span class="line"><span> - {{ . }}</span></span> +<span class="line"><span>{{ end }}</span></span></code></pre> + </div> <p> <code>text/template</code> の <code>.</code> は、現在の操作対象を表す特殊なオブジェクトである。 @@ -97,18 +98,20 @@ つまりこのテンプレートは、次のような構造をレンダリングしている (<code>Execute()</code> の第2引数)。 </p> - <pre class="highlight" language="go"><code class="highlight">tmpl.Execute(out, Params{ - Title: <span class="hljs-string">"foo"</span>, - User: User{ - ID: <span class="hljs-number">123</span>, - Name: <span class="hljs-string">"john"</span>, - }, - Items: []<span class="hljs-type">string</span>{ - <span class="hljs-string">"hoge"</span>, - <span class="hljs-string">"piyo"</span>, - <span class="hljs-string">"fuga"</span>, - }, -})</code></pre> + <div class="codeblock" language="go"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">tmpl.</span><span style="color:#6F42C1">Execute</span><span style="color:#24292E">(out, </span><span style="color:#6F42C1">Params</span><span style="color:#24292E">{</span></span> +<span class="line"><span style="color:#24292E"> Title: </span><span style="color:#032F62">"foo"</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E"> User: </span><span style="color:#6F42C1">User</span><span style="color:#24292E">{</span></span> +<span class="line"><span style="color:#24292E"> ID: </span><span style="color:#005CC5">123</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E"> Name: </span><span style="color:#032F62">"john"</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E"> },</span></span> +<span class="line"><span style="color:#24292E"> Items: []</span><span style="color:#D73A49">string</span><span style="color:#24292E">{</span></span> +<span class="line"><span style="color:#032F62"> "hoge"</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#032F62"> "piyo"</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#032F62"> "fuga"</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E"> },</span></span> +<span class="line"><span style="color:#24292E">})</span></span></code></pre> + </div> </section> <section id="section--what-i-want-to-do"> @@ -117,13 +120,15 @@ 今回おこないたいのは、<code>with</code> や <code>range</code> の中で、その外側で使われていたトップレベルのオブジェクトを参照することだ。 </p> - <pre class="highlight"><code>{{ with .User }} - ここから .Title を参照するには? -{{ end }} - -{{ range .Items }} - ここから .User を参照するには? -{{ end }}</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>{{ with .User }}</span></span> +<span class="line"><span> ここから .Title を参照するには?</span></span> +<span class="line"><span>{{ end }}</span></span> +<span class="line"><span></span></span> +<span class="line"><span>{{ range .Items }}</span></span> +<span class="line"><span> ここから .User を参照するには?</span></span> +<span class="line"><span>{{ end }}</span></span></code></pre> + </div> <p> <code>with</code> や <code>range</code> は、<code>.</code> を自身の対象オブジェクトに変更するので、単に <code>{{ with .User }}</code> の中で <code>.Title</code> と書いても、それは <code>User</code> の <code>Title</code> プロパティを参照しているとみなされる。 @@ -133,7 +138,9 @@ <code>text/template</code> では変数が使えるので、テンプレートの先頭で </p> - <pre class="highlight"><code>{{ $params := . }}</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>{{ $params := . }}</span></span></code></pre> + </div> <p> とでもしておけば実現は可能である。 @@ -150,13 +157,15 @@ 常にトップレベルを指す特殊変数 <code>$</code> を使えばよい。 </p> - <pre class="highlight"><code>{{ with .User }} - {{ $.Title }} -{{ end }} - -{{ range .Items }} - {{ $.User.Name }} -{{ end }}</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>{{ with .User }}</span></span> +<span class="line"><span> {{ $.Title }}</span></span> +<span class="line"><span>{{ end }}</span></span> +<span class="line"><span></span></span> +<span class="line"><span>{{ range .Items }}</span></span> +<span class="line"><span> {{ $.User.Name }}</span></span> +<span class="line"><span>{{ end }}</span></span></code></pre> + </div> <p> <code>$</code> は、テンプレートが実行されるときに渡されたオブジェクトを指す。これを使えば現在の <code>.</code> に関係なくトップレベルを参照できる。 diff --git a/vhosts/blog/public/posts/2024-09-28/mncore-challenge-1/index.html b/vhosts/blog/public/posts/2024-09-28/mncore-challenge-1/index.html index 640f0af8..bb998a4b 100644 --- a/vhosts/blog/public/posts/2024-09-28/mncore-challenge-1/index.html +++ b/vhosts/blog/public/posts/2024-09-28/mncore-challenge-1/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>MN-Core Challenge #1 参加レポ|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> diff --git a/vhosts/blog/public/posts/2024-12-04/cohackpp-report/index.html b/vhosts/blog/public/posts/2024-12-04/cohackpp-report/index.html index f98a752d..97f8e6b3 100644 --- a/vhosts/blog/public/posts/2024-12-04/cohackpp-report/index.html +++ b/vhosts/blog/public/posts/2024-12-04/cohackpp-report/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>紅白ぺぱ合戦に参加&LTしました|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -146,129 +145,131 @@ <a href="https://github.com/nsfisis/cohackpp/blob/main/congrats.php" rel="noreferrer" target="_blank">https://github.com/nsfisis/cohackpp/blob/main/congrats.php</a> </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> -<span class="hljs-variable">$s</span>=<span class="hljs-string"><<<'Q' -<?php -% -$s=<<<'Q</span><span class="hljs-string">' -@$c=[`]; -$m="";for($k=0;$k<min(13,intdiv(__LINE__-119,80)+1);$k++){$C=str_replace("\n","", -$c[$k]);$f=!0;foreach(str_split(base64_decode($C))as$l){$L=ord($l);$m.=str_repeat -($f?"#":chr(32),$L&127);$f=!$f;if($L&128){$m.="\n";$f=!0;continue;}}}print( -str_replace([chr(96),chr(37),chr(64)],[implode("\n",array_map(fn($C)=>"'</span><span class="hljs-string">".trim( -chunk_split(str_replace("</span>\n<span class="hljs-string">","</span><span class="hljs-string">",<span class="hljs-subst">$C</span>),80,"</span>\n<span class="hljs-string">"))."</span><span class="hljs-string">',",$c)),"\n{$m}","{$s}\nQ;\n"],$s)); -Q; -$c=['</span><span class="hljs-number">0</span>AFOgQFOgQFOgQFOgQFOgQFEAgiBAUIECIEBQwQHgQE8AQYFBoEBOgQGBAaBAToEBwQFgQE6BQYFBIEB -OwQHBASBATwEBgUDgQE8BQYEA4EBPQQGBAOBAT0FBgEFgQERBhsIBAQMgQERKQQFC4EBESkFAQ6BAREp -FIEBESkUgQERKRSBAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6B -AU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAQ4EPIEBDQY7gQENBjuBAQ0GO4EBDQU8gQENBTyBAQwG -PIEBDAY8gQEMBjyBAQwGPIEBDAY8gQEMBjyBAQwHO4EBDAc7gQENBzqBAQ0IOYEBDgg4gQEOCiUCD4EB -DwwdBw+BARAQDhEPgQERLg+BARItD4EBFCsPgQEXJRKBARsbGIEBToEBToEBToEBToEBToHQ<span class="hljs-string">', -'</span><span class="hljs-number">0</span>AFOgQFOgQFOgQEPASMFFoEBDwMhBRaBAQ4FIAUWgQEOBSAFFoEBDQUhBRaBAQ0FIQUWgQEMBSIFFoEB -DAUiBRaBAQsFIwUWgQELBQgBGgUWgQEKBQkDGAUWgQEKBQgGBCoDgQEJBQkFBSoDgQEFAQMECQYFKgOB -AQQDAQUJBQYqA4EBBAgJBQcqA4EBAwkJBRkFFoEBBAcJBRoFFoEBBQYIBRsFFoEBBgYHBRsFFoEBBwYF -BRwFFoEBCAYDBR0FFoEBCQYCBR0FFoEBCgseBRaBAQsJHwUWgQEMByAFFoEBDAcFAxgFFoEBDQUFBBgF -FoEBDQQGBRYGFoEBDAUHBAcmBYEBCwUIBQYmBYEBCwQKBAYmBYEBCgQLBQUmBYEBCQUMBS+BAQgFDAYv -gQEDHC+BAQMdLoEBAx0ugQEDHi2BAQMJBAUIBC2BARAFCAQtgQEQBQgELYEBEAUJAS+BARAFESEHgQEQ -BREhB4EBBwEIBQYBCiEHgQEHBAUFBAQJIQeBAQcEBQUEBAkEGAUHgQEGBQUFBAUIBBgFB4EBBgUFBQUE -CAQYBQeBAQYFBQUFBAgEGAUHgQEGBAYFBQUHBBgFB4EBBgQGBQYEBwQYBQeBAQUFBgUGBQYEGAUHgQEF -BQYFBwQGBBgFB4EBBQQHBQcEBgQYBQeBAQUEBwUHBQUEGAUHgQEEBQcFBwUFBBgFB4EBBAUHBQgEBQQY -BQeBAQQECAUIBAUEGAUHgQEDBQgFCAEIBBgFB4EBAwUIBREEGAUHgQECBQkFEQQYBQeBAQIFCQURIQeB -AQQCCgURIQeBARAFESEHgQEQBREhB4EBEAURIQeBARAFEQQYBQeBARAFEQQYBQeBARAFEQQYBQeBARAF -EQQYBQeBAU6BAU6BAU6B0A==<span class="hljs-string">', -'</span><span class="hljs-number">0</span>AFOgQFOgQFOgQEOAjEBDIEBDgUqBwqBAQ0FJwwJgQENBSETCIEBDQURAQcXDIEBDQURGxCBAQ0FERcU -gQENBBIOBAUUgQEMBRIGDAUUgQEMBRIFDQUUgQEMBRIFDgQUgQEMBRIFDgQUgQEMBBMFDgQUgQELBRMF -DgQUgQELBRMFDgUTgQELBRMFDgUTgQEDGQcFDgUTgQEDGwUoA4EBAxsFKAOBAQMbBSgDgQEDGwUoA4EB -CgUKBQUFDwUSgQEKBAsEBgUQBBKBAQkFCwQGBRAFEYEBCQULBAYFEAURgQEJBQoFBgUQBRGBAQkFCgUG -BREFEIEBCQQLBQYFEQUQgQEIBQsFBgUSBQkBBYEBCAULBQYFEgUJAwOBAQgFCwUGBQoFBAUIBAKBAQgF -CwQHBQQLBAYHAwOBAQgECwUHFAUGBQQDgQEHBQsFAxgFBwQEA4EBBwULBQMVCQ4DgQEHBQsFAw8QDQOB -AQcEDAUDCRcLBIEBBgULBQUCHwgFgQEGBQsFKAQHgQEGBQsFM4EBBgULBTOBAQYFCgUKIgiBAQUHCQUK -IgiBAQUICAUKIgiBAQUKBgUKIgiBAQULBAULBRgFCIEBBA0DBQsFGAUIgQEEBQIHAgULBRgFCIEBBgMD -DAwFGAUIgQENCwwFGAUIgQEOCgwFGAUIgQEQBw0FGAUIgQERBwwFGAUIgQERCAsiCIEBEAoKIgiBARAL -CSIIgQEPDQgiCIEBDwUCBwcFGAUIgQEOBgMHBgUYBQiBAQ0GBQcFBRgFCIEBDAcGBgUFGAUIgQELBwgE -BgUYBQiBAQoHCgMGBRgFCIEBCQcMAQcFGAUIgQEIBxUFGAUIgQEHCBUiCIEBBggWIgiBAQQJFyIIgQEF -BxgiCIEBBQUaBRgFCIEBBgMbBRgFCIEBJAUYBQiBAU6BAU6BAU6B0A==<span class="hljs-string">', -'</span><span class="hljs-number">0</span>AFOgQFOgQFOgQFOgQFOgQFOgQFOgQEZBi+BARkGL4EBGgUvgQEaBS+BARoFL4EBGgUvgQEaBS+BARoF -L4EBGgUvgQEaBRkBFYEBGgUZAxOBARoFDwEIBRKBARoFCwUIBxCBARoFBgoHCg6BARoVCQkNgQEJJgsJ -C4EBCSYMCQqBAQohEgkIgQEKGxoIB4EBChUhCQWBARkFIwkEgQEZBSUGBYEBGQUmBAaBARkFKAIGgQEZ -BTCBARkFMIEBGQUwgQEZBTCBARkFMIEBGQUwgQEZBTCBARkFCRAXgQEZBQQYFIEBGSMSgQEZJBGBARkS -CAwPgQEXDhIJDoEBFQwYCA2BARMMGwcNgQESDB0HDIEBEA4eBgyBAQ8IAwQfBguBAQ4IBAQfBguBAQ0H -BgQgBQuBAQwHBwQgBQuBAQsHCAUfBQuBAQoGCgUfBQuBAQoGCgUfBQuBAQkGCwUfBQuBAQkFDAUeBguB -AQgGDAUeBguBAQgGDAUdBwuBAQgGDAUdBgyBAQgGDAUcBwyBAQkFDAUbBw2BAQkGCwUZCQ2BAQkHCgUY -CQ6BAQoIBwYVCw+BAQsIBQcSDRCBAQwSChURgQENEQoTE4EBDhAKERWBARANDA4XgQESCwwLGoEBFQYO -BSCBAU6BAU6BAU6BAU6BAU6BAU6B0A==<span class="hljs-string">', -'</span><span class="hljs-number">0</span>AFOgQFOgQFOgQFOgQFOgQFOgQFOgQEuBhqBAS4FG4EBLgUbgQEuBRuBARICGQYbgQEPBRkGG4EBDgYZ -BRyBAQ8FGQUcgQEPBhgFHIEBDwYXBhyBARAFFwUdgQEQBRcFHYEBEAYNERqBAREFChcXgQERBQccFYEB -EQYEIBOBARIFAg4DExGBARIRBwYEChCBARIOCgUHCQ+BARMKDQUJCA6BARIJDgYKCA2BAREIEAUNBwyB -ARAJEAUOBgyBAQ8KDwYPBguBAQ4MDgUQBwqBAQ4MDgURBgqBAQ0GAgYMBRMFCoEBDAYEBQwFEwYJgQEM -BgQFCwYTBgmBAQsGBQYKBRUFCYEBCgYHBQkGFQYIgQEKBQgGCAYVBgiBAQkGCQUIBRcFCIEBCQUKBgYG -FwUIgQEJBQsFBgUYBQiBAQgFDAYEBhgFCIEBCAUNBQMGGQUIgQEIBQ0GAgYZBQiBAQcFDwwaBQiBAQcF -DwwaBQiBAQcFEAobBQiBAQcFEAoaBgiBAQcFEQgbBgiBAQcFEgYcBgiBAQcFEQgbBQmBAQcFEAoZBgmB -AQcFEAoZBgmBAQcFDwwXBgqBAQcFDg4VBwqBAQcGDAcCBxQGC4EBCAULBwQEFQcLgQEIBggIBgIVBwyB -AQgIBAkHARUHDYEBCRMcCQ2BAQoRHAkOgQELDhwKD4EBDAwbChGBAQ4HGwwSgQEsDxOBASgRFYEBKQ4X -gQEpDBmBASoIHIEBKwMggQFOgQFOgQFOgQFOgQFOgQFOgQFOgdA=<span class="hljs-string">', -'</span><span class="hljs-number">0</span>AFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQE1DwqBASkbCoEBHiYKgQETMQqBAQc9CoEBBjQU -gQEGIQQKGYEBBhcOBxyBAQcOFAcegQEHBhsHH4EBJwYhgQEmBiKBASUGFgEMgQEkBhUDDIEBIwYWBAuB -ASMGFwQKgQEiBg8DBgQKgQEhBg8EBwQJgQEhBhAEBwQIgQEgBhEFBgQIgQEgBRMEBwQHgQEfBhQEBgUG -gQEfBhQEBwQGgQEfBRYEBgIIgQEeBhYEEIEBHgYXBA+BAR4FGAMQgQEeBSuBAR0GK4EBHQYrgQEdBiuB -AR0GK4EBHQYrgQEdBiuBAR0GK4EBHQYrgQEdBiuBAR4FK4EBHgYqgQEeBiqBAR4HKYEBHwYpgQEfByiB -ASAHJ4EBIAcngQEhByaBASEJJIEBIgkjgQEjCiGBASQLH4EBJQwdgQEmDxmBASgTE4EBKhMRgQErEhGB -AS4PEYEBMAwSgQE0CBKBAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6B0A==<span class="hljs-string">', -'</span><span class="hljs-number">0</span>AFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQEXATaBARQENoEBEgY2gQESBzWBARMGNYEBEwc0gQEUBjSB -ARQGNIEBFQYzgQEVBiABEoEBFgYeAxGBARYGHAYQgQEWBxoHEIEBFwYYCg+BARcHFQsQgQEYBhMLEoEB -GAYRCxSBARkGDgsWgQEZBgwLGIEBGgYJCxqBARoHBwocgQEbBgUKHoEBGwcCCiCBARwRIYEBHA8jgQEd -DCWBAR0KJ4EBHAoogQEbCSqBARoILIEBGQgtgQEXCC+BARYIMIEBFQgxgQEVBzKBARQHM4EBEwc0gQES -BzWBARIGNoEBEQY3gQERBjeBAREFOIEBEAY4gQEQBjiBARAGOIEBEAY4gQEQBjiBARAGOIEBEAY4gQEQ -BjiBARAHN4EBEAc3gQERBzaBAREINYEBEgkzgQETCiEDDYEBEw0WCw2BARQtDYEBFisNgQEXKg2BARon -DYEBHSARgQEjDxyBAU6BAU6BAU6BAU6BAU6BAU6BAU6B0A==<span class="hljs-string">', -'</span><span class="hljs-number">0</span>AFOgQFOgQFOgQFOgQFOgQFOgQFOgQEXBDOBARcLLIEBFxQjgQEXIRaBARchFoEBGh4WgQEiFhaBASsN -FoEBNgEXgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQEkDR2BAR4WGoEBGR0YgQEVIxaBARApFYEB -DRcLCxSBAQ4QFAkTgQEODBoIEoEBDgkeBxKBAQ4GIgcRgQEPAiYGEYEBNwcQgQE4BhCBATgGEIEBOAYQ -gQE4BhCBATkFEIEBOQUQgQE5BRCBATgGEIEBOAYQgQE4BhCBATgGEIEBNwcQgQE3BhGBATcGEYEBNgcR -gQE1BxKBATUHEoEBNAcTgQEzCBOBATIIFIEBMQgVgQEvCRaBAS4JF4EBLAoYgQEqCxmBAScMG4EBJQ0c -gQEhDx6BARwTH4EBGBQigQEZESSBARoNJ4EBGgoqgQEbBS6BAU6BAU6BAU6BAU6BAU6BAU6BAU6B0A==<span class="hljs-string">', -'</span><span class="hljs-number">0</span>AFOgQFOgQFOgQFOgQFOgQFDAgmBAUEECYEBQgQIgQE7AQYFB4EBOQQGBAeBATkEBwQGgQE5BQYFBYEB -OgQHBAWBATsEBgUEgQE7BQYEBIEBPAQGBASBATwFBgEGgQEQBhsIBAQNgQEQKQQFDIEBECkFAQ+BARAp -FYEBECkVgQEQKRWBAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6B -AU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAQ0EPYEBDAY8gQEMBjyBAQwGPIEBDAU9gQEMBT2BAQsG -PYEBCwY9gQELBj2BAQsGPYEBCwY9gQELBj2BAQsHPIEBCwc8gQEMBzuBAQwIOoEBDQg5gQENCiUCEIEB -DgwdBxCBAQ8QDhEQgQEQLhCBAREtEIEBEysQgQEWJROBARobGYEBToEBToEBToEBToEBToHQ<span class="hljs-string">', -'</span><span class="hljs-number">0</span>AFOgQFOgQFOgQFOgQFCAwmBAUEECYEBQQUIgQE5AwYFB4EBOAQHBAeBASkCDgQGBQaBASYGDQUGBAaB -ASYGDgQHBAWBASYGDgUGBAWBAScFDwQHBASBAScGDwQGAwWBAScGDwUNgQEoBRAEDYEBKAUQAw6BASgG -IIEBKQUQAw2BASkFDAcNgQEpBgYMDYEBCgMdFw2BAQsVAh8NgQELNQ6BAQsxEoEBCysYgQELJh2BARkI -CwUdgQEsBhyBAS0FHIEBLQUcgQEuBRuBAS4FG4EBLwUagQEvBRqBATAFGYEBMAYYgQExBRiBATEGF4EB -MgUXgQEyBhaBATMGFYEBNAUVgQE0BhSBATUGE4EBEAIWCgMHEoEBEAYSFRGBAQ8GExURgQEPBRQUEoEB -DgYaDROBAQ4GIwQTgQEOBTuBAQ0GO4EBDQY7gQENBTyBAQ0FPIEBDQU8gQENBTyBAQ0FPIEBDQU8gQEN -BjuBAQ0GO4EBDgY6gQEOBzmBAQ4IOIEBDwg3gQEQCh4BFYEBEQwVBxWBARInFYEBEyYVgQEVJBWBARgh -FYEBGxoZgQFOgQFOgQFOgQFOgdA=<span class="hljs-string">', -'</span><span class="hljs-number">0</span>AFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQEJBz6BAQkGP4EBCQY/gQEJBigDFIEB -CQYlBhSBAQkGJQcTgQEJBiYHEoEBCQYnBhKBAQkGJwcRgQEJBigGEYEBCQYoBxCBAQkGKQYQgQEJBioG -D4EBCQYqBg+BAQkGKgcOgQEJBisGDoEBCgUrBg6BAQoFLAYNgQEKBSwGDYEBCgUtBgyBAQoFLQYMgQEK -BS0GDIEBCgUuBguBAQoFLgYLgQEKBS4GC4EBCgYtBguBAQoGLgYKgQEKBi4GCoEBCgYuBgqBAQoGLwYJ -gQELBS8GCYEBCwUvBgmBAQsFLwYJgQELBhMBGgYJgQELBhMCGgYIgQELBhMDGQYIgQEMBRMEGAYIgQEM -BhEGFwYIgQEMBhEGFwYIgQEMBhAGGQUIgQENBg8GGQUIgQENBg8GGQUIgQENBg4GGgILgQEOBg0GJ4EB -DgcLBiiBAQ4HCgcogQEPBwgHKYEBEAcGCCmBARAKAQkqgQEREiuBARIRK4EBEhAsgQETDi2BARULLoEB -FwcwgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgdA=<span class="hljs-string">', -'</span><span class="hljs-number">0</span>AFOgQFOgQFOgQFOgQFOgQFOgQFOgQElBiOBASYFI4EBJgUjgQEmBSOBASYFI4EBJgUjgQEmBSOBASYF -I4EBJgUQBQ6BAQ4IEAUGDw6BAQ4yDoEBDjIOgQEOMg6BAQ4rFYEBGhIigQEmBSOBASYFI4EBJgUjgQEm -BSOBASYFI4EBJgUjgQEmBSOBASYFI4EBJgUjgQEmBRQCDYEBDQMWBQwKDYEBDQ8JHA2BAQ4zDYEBDjMN -gQEOMg6BARAnF4EBJQYjgQEmBSOBASYFI4EBJgUjgQEmBSOBASYFI4EBJgUjgQEmBSOBASYFI4EBJgUj -gQEmBSOBAR0EBQUjgQEXFCOBARQZIYEBEh4egQERIRyBARAJDBAZgQEPBxARF4EBDgYSExWBAQ4FEwYD -CxSBAQ4FEwYFCxKBAQ0FFAYHChGBAQ0FFAYJCg+BAQ0FFAYKCg6BAQ0GEwYMCQ2BAQ4FEwYNCQyBAQ4G -EQYQBg2BAQ4HDwcRBQ2BAQ8IDAgSAw6BAQ8bFAEPgQERGCWBARIWJoEBFBIogQEXDSqBAU6BAU6BAU6B -AU6BAU6BAU6B0A==<span class="hljs-string">', -'</span><span class="hljs-number">0</span>AFOgQFOgQFOgQFOgQFOgQFOgQEpBh+BASkGH4EBKQYfgQEqBR+BASoFH4EBKgUfgQEqBR+BASoFH4EB -KgUfgQEqBR+BARkuB4EBBkEHgQEHQAeBAQdAB4EBB0AHgQEHDBcFH4EBKgUfgQEqBR+BASoFH4EBKgUf -gQEqBR+BASoFH4EBKgUfgQEgDx+BAR4RH4EBHBMfgQEbFB+BARoIBAkfgQEZBwkGH4EBGQYLBh6BARgG -DQUegQEYBQ4GHYEBFwYPBR2BARcFEAUdgQEXBRAFHYEBFwUQBhyBARcFEAYcgQEXBQ8HHIEBFwUPBxyB -ARcGDgccgQEXBg0IHIEBGAYMBx2BARgHCggdgQEZCAYKHYEBGhcdgQEbFh2BARwVHYEBHgsBBh6BASAG -BAYegQEpBh+BASkGH4EBKAYggQEnByCBASYHIYEBJQcigQEkCCKBASIJI4EBIAokgQEeCyWBARwLJ4EB -GQ0ogQEWDiqBARcMK4EBGAktgQEZBTCBARoCMoEBToEBToEBToEBToEBToEBToHQ<span class="hljs-string">',]; -$m="";for($k=0;$k<min(13,intdiv(__LINE__-119,80)+1);$k++){$C=str_replace("\n","", -$c[$k]);$f=!0;foreach(str_split(base64_decode($C))as$l){$L=ord($l);$m.=str_repeat -($f?"#":chr(32),$L&127);$f=!$f;if($L&128){$m.="\n";$f=!0;continue;}}}print( -str_replace([chr(96),chr(37),chr(64)],[implode("\n",array_map(fn($C)=>"'</span><span class="hljs-string">".trim( -chunk_split(str_replace("</span>\n<span class="hljs-string">","</span><span class="hljs-string">",<span class="hljs-subst">$C</span>),80,"</span>\n<span class="hljs-string">"))."</span><span class="hljs-string">',",$c)),"\n{$m}","{$s}\nQ;\n"],$s));</span></code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> +<span class="line"><span style="color:#24292E">$s</span><span style="color:#D73A49">=</span><span style="color:#032F62"><<<'</span><span style="color:#D73A49">Q</span><span style="color:#032F62">'</span></span> +<span class="line"><span style="color:#032F62"><?php</span></span> +<span class="line"><span style="color:#032F62">%</span></span> +<span class="line"><span style="color:#032F62">$s=<<<'Q'</span></span> +<span class="line"><span style="color:#032F62">@$c=[`];</span></span> +<span class="line"><span style="color:#032F62">$m="";for($k=0;$k<min(13,intdiv(__LINE__-119,80)+1);$k++){$C=str_replace("\n","",</span></span> +<span class="line"><span style="color:#032F62">$c[$k]);$f=!0;foreach(str_split(base64_decode($C))as$l){$L=ord($l);$m.=str_repeat</span></span> +<span class="line"><span style="color:#032F62">($f?"#":chr(32),$L&127);$f=!$f;if($L&128){$m.="\n";$f=!0;continue;}}}print(</span></span> +<span class="line"><span style="color:#032F62">str_replace([chr(96),chr(37),chr(64)],[implode("\n",array_map(fn($C)=>"'".trim(</span></span> +<span class="line"><span style="color:#032F62">chunk_split(str_replace("\n","",$C),80,"\n"))."',",$c)),"\n{$m}","{$s}\nQ;\n"],$s));</span></span> +<span class="line"><span style="color:#D73A49">Q</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$c</span><span style="color:#D73A49">=</span><span style="color:#24292E">[</span><span style="color:#032F62">'0AFOgQFOgQFOgQFOgQFOgQFEAgiBAUIECIEBQwQHgQE8AQYFBoEBOgQGBAaBAToEBwQFgQE6BQYFBIEB</span></span> +<span class="line"><span style="color:#032F62">OwQHBASBATwEBgUDgQE8BQYEA4EBPQQGBAOBAT0FBgEFgQERBhsIBAQMgQERKQQFC4EBESkFAQ6BAREp</span></span> +<span class="line"><span style="color:#032F62">FIEBESkUgQERKRSBAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6B</span></span> +<span class="line"><span style="color:#032F62">AU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAQ4EPIEBDQY7gQENBjuBAQ0GO4EBDQU8gQENBTyBAQwG</span></span> +<span class="line"><span style="color:#032F62">PIEBDAY8gQEMBjyBAQwGPIEBDAY8gQEMBjyBAQwHO4EBDAc7gQENBzqBAQ0IOYEBDgg4gQEOCiUCD4EB</span></span> +<span class="line"><span style="color:#032F62">DwwdBw+BARAQDhEPgQERLg+BARItD4EBFCsPgQEXJRKBARsbGIEBToEBToEBToEBToEBToHQ'</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#032F62">'0AFOgQFOgQFOgQEPASMFFoEBDwMhBRaBAQ4FIAUWgQEOBSAFFoEBDQUhBRaBAQ0FIQUWgQEMBSIFFoEB</span></span> +<span class="line"><span style="color:#032F62">DAUiBRaBAQsFIwUWgQELBQgBGgUWgQEKBQkDGAUWgQEKBQgGBCoDgQEJBQkFBSoDgQEFAQMECQYFKgOB</span></span> +<span class="line"><span style="color:#032F62">AQQDAQUJBQYqA4EBBAgJBQcqA4EBAwkJBRkFFoEBBAcJBRoFFoEBBQYIBRsFFoEBBgYHBRsFFoEBBwYF</span></span> +<span class="line"><span style="color:#032F62">BRwFFoEBCAYDBR0FFoEBCQYCBR0FFoEBCgseBRaBAQsJHwUWgQEMByAFFoEBDAcFAxgFFoEBDQUFBBgF</span></span> +<span class="line"><span style="color:#032F62">FoEBDQQGBRYGFoEBDAUHBAcmBYEBCwUIBQYmBYEBCwQKBAYmBYEBCgQLBQUmBYEBCQUMBS+BAQgFDAYv</span></span> +<span class="line"><span style="color:#032F62">gQEDHC+BAQMdLoEBAx0ugQEDHi2BAQMJBAUIBC2BARAFCAQtgQEQBQgELYEBEAUJAS+BARAFESEHgQEQ</span></span> +<span class="line"><span style="color:#032F62">BREhB4EBBwEIBQYBCiEHgQEHBAUFBAQJIQeBAQcEBQUEBAkEGAUHgQEGBQUFBAUIBBgFB4EBBgUFBQUE</span></span> +<span class="line"><span style="color:#032F62">CAQYBQeBAQYFBQUFBAgEGAUHgQEGBAYFBQUHBBgFB4EBBgQGBQYEBwQYBQeBAQUFBgUGBQYEGAUHgQEF</span></span> +<span class="line"><span style="color:#032F62">BQYFBwQGBBgFB4EBBQQHBQcEBgQYBQeBAQUEBwUHBQUEGAUHgQEEBQcFBwUFBBgFB4EBBAUHBQgEBQQY</span></span> +<span class="line"><span style="color:#032F62">BQeBAQQECAUIBAUEGAUHgQEDBQgFCAEIBBgFB4EBAwUIBREEGAUHgQECBQkFEQQYBQeBAQIFCQURIQeB</span></span> +<span class="line"><span style="color:#032F62">AQQCCgURIQeBARAFESEHgQEQBREhB4EBEAURIQeBARAFEQQYBQeBARAFEQQYBQeBARAFEQQYBQeBARAF</span></span> +<span class="line"><span style="color:#032F62">EQQYBQeBAU6BAU6BAU6B0A=='</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#032F62">'0AFOgQFOgQFOgQEOAjEBDIEBDgUqBwqBAQ0FJwwJgQENBSETCIEBDQURAQcXDIEBDQURGxCBAQ0FERcU</span></span> +<span class="line"><span style="color:#032F62">gQENBBIOBAUUgQEMBRIGDAUUgQEMBRIFDQUUgQEMBRIFDgQUgQEMBRIFDgQUgQEMBBMFDgQUgQELBRMF</span></span> +<span class="line"><span style="color:#032F62">DgQUgQELBRMFDgUTgQELBRMFDgUTgQEDGQcFDgUTgQEDGwUoA4EBAxsFKAOBAQMbBSgDgQEDGwUoA4EB</span></span> +<span class="line"><span style="color:#032F62">CgUKBQUFDwUSgQEKBAsEBgUQBBKBAQkFCwQGBRAFEYEBCQULBAYFEAURgQEJBQoFBgUQBRGBAQkFCgUG</span></span> +<span class="line"><span style="color:#032F62">BREFEIEBCQQLBQYFEQUQgQEIBQsFBgUSBQkBBYEBCAULBQYFEgUJAwOBAQgFCwUGBQoFBAUIBAKBAQgF</span></span> +<span class="line"><span style="color:#032F62">CwQHBQQLBAYHAwOBAQgECwUHFAUGBQQDgQEHBQsFAxgFBwQEA4EBBwULBQMVCQ4DgQEHBQsFAw8QDQOB</span></span> +<span class="line"><span style="color:#032F62">AQcEDAUDCRcLBIEBBgULBQUCHwgFgQEGBQsFKAQHgQEGBQsFM4EBBgULBTOBAQYFCgUKIgiBAQUHCQUK</span></span> +<span class="line"><span style="color:#032F62">IgiBAQUICAUKIgiBAQUKBgUKIgiBAQULBAULBRgFCIEBBA0DBQsFGAUIgQEEBQIHAgULBRgFCIEBBgMD</span></span> +<span class="line"><span style="color:#032F62">DAwFGAUIgQENCwwFGAUIgQEOCgwFGAUIgQEQBw0FGAUIgQERBwwFGAUIgQERCAsiCIEBEAoKIgiBARAL</span></span> +<span class="line"><span style="color:#032F62">CSIIgQEPDQgiCIEBDwUCBwcFGAUIgQEOBgMHBgUYBQiBAQ0GBQcFBRgFCIEBDAcGBgUFGAUIgQELBwgE</span></span> +<span class="line"><span style="color:#032F62">BgUYBQiBAQoHCgMGBRgFCIEBCQcMAQcFGAUIgQEIBxUFGAUIgQEHCBUiCIEBBggWIgiBAQQJFyIIgQEF</span></span> +<span class="line"><span style="color:#032F62">BxgiCIEBBQUaBRgFCIEBBgMbBRgFCIEBJAUYBQiBAU6BAU6BAU6B0A=='</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#032F62">'0AFOgQFOgQFOgQFOgQFOgQFOgQFOgQEZBi+BARkGL4EBGgUvgQEaBS+BARoFL4EBGgUvgQEaBS+BARoF</span></span> +<span class="line"><span style="color:#032F62">L4EBGgUvgQEaBRkBFYEBGgUZAxOBARoFDwEIBRKBARoFCwUIBxCBARoFBgoHCg6BARoVCQkNgQEJJgsJ</span></span> +<span class="line"><span style="color:#032F62">C4EBCSYMCQqBAQohEgkIgQEKGxoIB4EBChUhCQWBARkFIwkEgQEZBSUGBYEBGQUmBAaBARkFKAIGgQEZ</span></span> +<span class="line"><span style="color:#032F62">BTCBARkFMIEBGQUwgQEZBTCBARkFMIEBGQUwgQEZBTCBARkFCRAXgQEZBQQYFIEBGSMSgQEZJBGBARkS</span></span> +<span class="line"><span style="color:#032F62">CAwPgQEXDhIJDoEBFQwYCA2BARMMGwcNgQESDB0HDIEBEA4eBgyBAQ8IAwQfBguBAQ4IBAQfBguBAQ0H</span></span> +<span class="line"><span style="color:#032F62">BgQgBQuBAQwHBwQgBQuBAQsHCAUfBQuBAQoGCgUfBQuBAQoGCgUfBQuBAQkGCwUfBQuBAQkFDAUeBguB</span></span> +<span class="line"><span style="color:#032F62">AQgGDAUeBguBAQgGDAUdBwuBAQgGDAUdBgyBAQgGDAUcBwyBAQkFDAUbBw2BAQkGCwUZCQ2BAQkHCgUY</span></span> +<span class="line"><span style="color:#032F62">CQ6BAQoIBwYVCw+BAQsIBQcSDRCBAQwSChURgQENEQoTE4EBDhAKERWBARANDA4XgQESCwwLGoEBFQYO</span></span> +<span class="line"><span style="color:#032F62">BSCBAU6BAU6BAU6BAU6BAU6BAU6B0A=='</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#032F62">'0AFOgQFOgQFOgQFOgQFOgQFOgQFOgQEuBhqBAS4FG4EBLgUbgQEuBRuBARICGQYbgQEPBRkGG4EBDgYZ</span></span> +<span class="line"><span style="color:#032F62">BRyBAQ8FGQUcgQEPBhgFHIEBDwYXBhyBARAFFwUdgQEQBRcFHYEBEAYNERqBAREFChcXgQERBQccFYEB</span></span> +<span class="line"><span style="color:#032F62">EQYEIBOBARIFAg4DExGBARIRBwYEChCBARIOCgUHCQ+BARMKDQUJCA6BARIJDgYKCA2BAREIEAUNBwyB</span></span> +<span class="line"><span style="color:#032F62">ARAJEAUOBgyBAQ8KDwYPBguBAQ4MDgUQBwqBAQ4MDgURBgqBAQ0GAgYMBRMFCoEBDAYEBQwFEwYJgQEM</span></span> +<span class="line"><span style="color:#032F62">BgQFCwYTBgmBAQsGBQYKBRUFCYEBCgYHBQkGFQYIgQEKBQgGCAYVBgiBAQkGCQUIBRcFCIEBCQUKBgYG</span></span> +<span class="line"><span style="color:#032F62">FwUIgQEJBQsFBgUYBQiBAQgFDAYEBhgFCIEBCAUNBQMGGQUIgQEIBQ0GAgYZBQiBAQcFDwwaBQiBAQcF</span></span> +<span class="line"><span style="color:#032F62">DwwaBQiBAQcFEAobBQiBAQcFEAoaBgiBAQcFEQgbBgiBAQcFEgYcBgiBAQcFEQgbBQmBAQcFEAoZBgmB</span></span> +<span class="line"><span style="color:#032F62">AQcFEAoZBgmBAQcFDwwXBgqBAQcFDg4VBwqBAQcGDAcCBxQGC4EBCAULBwQEFQcLgQEIBggIBgIVBwyB</span></span> +<span class="line"><span style="color:#032F62">AQgIBAkHARUHDYEBCRMcCQ2BAQoRHAkOgQELDhwKD4EBDAwbChGBAQ4HGwwSgQEsDxOBASgRFYEBKQ4X</span></span> +<span class="line"><span style="color:#032F62">gQEpDBmBASoIHIEBKwMggQFOgQFOgQFOgQFOgQFOgQFOgQFOgdA='</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#032F62">'0AFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQE1DwqBASkbCoEBHiYKgQETMQqBAQc9CoEBBjQU</span></span> +<span class="line"><span style="color:#032F62">gQEGIQQKGYEBBhcOBxyBAQcOFAcegQEHBhsHH4EBJwYhgQEmBiKBASUGFgEMgQEkBhUDDIEBIwYWBAuB</span></span> +<span class="line"><span style="color:#032F62">ASMGFwQKgQEiBg8DBgQKgQEhBg8EBwQJgQEhBhAEBwQIgQEgBhEFBgQIgQEgBRMEBwQHgQEfBhQEBgUG</span></span> +<span class="line"><span style="color:#032F62">gQEfBhQEBwQGgQEfBRYEBgIIgQEeBhYEEIEBHgYXBA+BAR4FGAMQgQEeBSuBAR0GK4EBHQYrgQEdBiuB</span></span> +<span class="line"><span style="color:#032F62">AR0GK4EBHQYrgQEdBiuBAR0GK4EBHQYrgQEdBiuBAR4FK4EBHgYqgQEeBiqBAR4HKYEBHwYpgQEfByiB</span></span> +<span class="line"><span style="color:#032F62">ASAHJ4EBIAcngQEhByaBASEJJIEBIgkjgQEjCiGBASQLH4EBJQwdgQEmDxmBASgTE4EBKhMRgQErEhGB</span></span> +<span class="line"><span style="color:#032F62">AS4PEYEBMAwSgQE0CBKBAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6B0A=='</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#032F62">'0AFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQEXATaBARQENoEBEgY2gQESBzWBARMGNYEBEwc0gQEUBjSB</span></span> +<span class="line"><span style="color:#032F62">ARQGNIEBFQYzgQEVBiABEoEBFgYeAxGBARYGHAYQgQEWBxoHEIEBFwYYCg+BARcHFQsQgQEYBhMLEoEB</span></span> +<span class="line"><span style="color:#032F62">GAYRCxSBARkGDgsWgQEZBgwLGIEBGgYJCxqBARoHBwocgQEbBgUKHoEBGwcCCiCBARwRIYEBHA8jgQEd</span></span> +<span class="line"><span style="color:#032F62">DCWBAR0KJ4EBHAoogQEbCSqBARoILIEBGQgtgQEXCC+BARYIMIEBFQgxgQEVBzKBARQHM4EBEwc0gQES</span></span> +<span class="line"><span style="color:#032F62">BzWBARIGNoEBEQY3gQERBjeBAREFOIEBEAY4gQEQBjiBARAGOIEBEAY4gQEQBjiBARAGOIEBEAY4gQEQ</span></span> +<span class="line"><span style="color:#032F62">BjiBARAHN4EBEAc3gQERBzaBAREINYEBEgkzgQETCiEDDYEBEw0WCw2BARQtDYEBFisNgQEXKg2BARon</span></span> +<span class="line"><span style="color:#032F62">DYEBHSARgQEjDxyBAU6BAU6BAU6BAU6BAU6BAU6BAU6B0A=='</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#032F62">'0AFOgQFOgQFOgQFOgQFOgQFOgQFOgQEXBDOBARcLLIEBFxQjgQEXIRaBARchFoEBGh4WgQEiFhaBASsN</span></span> +<span class="line"><span style="color:#032F62">FoEBNgEXgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQEkDR2BAR4WGoEBGR0YgQEVIxaBARApFYEB</span></span> +<span class="line"><span style="color:#032F62">DRcLCxSBAQ4QFAkTgQEODBoIEoEBDgkeBxKBAQ4GIgcRgQEPAiYGEYEBNwcQgQE4BhCBATgGEIEBOAYQ</span></span> +<span class="line"><span style="color:#032F62">gQE4BhCBATkFEIEBOQUQgQE5BRCBATgGEIEBOAYQgQE4BhCBATgGEIEBNwcQgQE3BhGBATcGEYEBNgcR</span></span> +<span class="line"><span style="color:#032F62">gQE1BxKBATUHEoEBNAcTgQEzCBOBATIIFIEBMQgVgQEvCRaBAS4JF4EBLAoYgQEqCxmBAScMG4EBJQ0c</span></span> +<span class="line"><span style="color:#032F62">gQEhDx6BARwTH4EBGBQigQEZESSBARoNJ4EBGgoqgQEbBS6BAU6BAU6BAU6BAU6BAU6BAU6BAU6B0A=='</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#032F62">'0AFOgQFOgQFOgQFOgQFOgQFDAgmBAUEECYEBQgQIgQE7AQYFB4EBOQQGBAeBATkEBwQGgQE5BQYFBYEB</span></span> +<span class="line"><span style="color:#032F62">OgQHBAWBATsEBgUEgQE7BQYEBIEBPAQGBASBATwFBgEGgQEQBhsIBAQNgQEQKQQFDIEBECkFAQ+BARAp</span></span> +<span class="line"><span style="color:#032F62">FYEBECkVgQEQKRWBAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6B</span></span> +<span class="line"><span style="color:#032F62">AU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAU6BAQ0EPYEBDAY8gQEMBjyBAQwGPIEBDAU9gQEMBT2BAQsG</span></span> +<span class="line"><span style="color:#032F62">PYEBCwY9gQELBj2BAQsGPYEBCwY9gQELBj2BAQsHPIEBCwc8gQEMBzuBAQwIOoEBDQg5gQENCiUCEIEB</span></span> +<span class="line"><span style="color:#032F62">DgwdBxCBAQ8QDhEQgQEQLhCBAREtEIEBEysQgQEWJROBARobGYEBToEBToEBToEBToEBToHQ'</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#032F62">'0AFOgQFOgQFOgQFOgQFCAwmBAUEECYEBQQUIgQE5AwYFB4EBOAQHBAeBASkCDgQGBQaBASYGDQUGBAaB</span></span> +<span class="line"><span style="color:#032F62">ASYGDgQHBAWBASYGDgUGBAWBAScFDwQHBASBAScGDwQGAwWBAScGDwUNgQEoBRAEDYEBKAUQAw6BASgG</span></span> +<span class="line"><span style="color:#032F62">IIEBKQUQAw2BASkFDAcNgQEpBgYMDYEBCgMdFw2BAQsVAh8NgQELNQ6BAQsxEoEBCysYgQELJh2BARkI</span></span> +<span class="line"><span style="color:#032F62">CwUdgQEsBhyBAS0FHIEBLQUcgQEuBRuBAS4FG4EBLwUagQEvBRqBATAFGYEBMAYYgQExBRiBATEGF4EB</span></span> +<span class="line"><span style="color:#032F62">MgUXgQEyBhaBATMGFYEBNAUVgQE0BhSBATUGE4EBEAIWCgMHEoEBEAYSFRGBAQ8GExURgQEPBRQUEoEB</span></span> +<span class="line"><span style="color:#032F62">DgYaDROBAQ4GIwQTgQEOBTuBAQ0GO4EBDQY7gQENBTyBAQ0FPIEBDQU8gQENBTyBAQ0FPIEBDQU8gQEN</span></span> +<span class="line"><span style="color:#032F62">BjuBAQ0GO4EBDgY6gQEOBzmBAQ4IOIEBDwg3gQEQCh4BFYEBEQwVBxWBARInFYEBEyYVgQEVJBWBARgh</span></span> +<span class="line"><span style="color:#032F62">FYEBGxoZgQFOgQFOgQFOgQFOgdA='</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#032F62">'0AFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQEJBz6BAQkGP4EBCQY/gQEJBigDFIEB</span></span> +<span class="line"><span style="color:#032F62">CQYlBhSBAQkGJQcTgQEJBiYHEoEBCQYnBhKBAQkGJwcRgQEJBigGEYEBCQYoBxCBAQkGKQYQgQEJBioG</span></span> +<span class="line"><span style="color:#032F62">D4EBCQYqBg+BAQkGKgcOgQEJBisGDoEBCgUrBg6BAQoFLAYNgQEKBSwGDYEBCgUtBgyBAQoFLQYMgQEK</span></span> +<span class="line"><span style="color:#032F62">BS0GDIEBCgUuBguBAQoFLgYLgQEKBS4GC4EBCgYtBguBAQoGLgYKgQEKBi4GCoEBCgYuBgqBAQoGLwYJ</span></span> +<span class="line"><span style="color:#032F62">gQELBS8GCYEBCwUvBgmBAQsFLwYJgQELBhMBGgYJgQELBhMCGgYIgQELBhMDGQYIgQEMBRMEGAYIgQEM</span></span> +<span class="line"><span style="color:#032F62">BhEGFwYIgQEMBhEGFwYIgQEMBhAGGQUIgQENBg8GGQUIgQENBg8GGQUIgQENBg4GGgILgQEOBg0GJ4EB</span></span> +<span class="line"><span style="color:#032F62">DgcLBiiBAQ4HCgcogQEPBwgHKYEBEAcGCCmBARAKAQkqgQEREiuBARIRK4EBEhAsgQETDi2BARULLoEB</span></span> +<span class="line"><span style="color:#032F62">FwcwgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgQFOgdA='</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#032F62">'0AFOgQFOgQFOgQFOgQFOgQFOgQFOgQElBiOBASYFI4EBJgUjgQEmBSOBASYFI4EBJgUjgQEmBSOBASYF</span></span> +<span class="line"><span style="color:#032F62">I4EBJgUQBQ6BAQ4IEAUGDw6BAQ4yDoEBDjIOgQEOMg6BAQ4rFYEBGhIigQEmBSOBASYFI4EBJgUjgQEm</span></span> +<span class="line"><span style="color:#032F62">BSOBASYFI4EBJgUjgQEmBSOBASYFI4EBJgUjgQEmBRQCDYEBDQMWBQwKDYEBDQ8JHA2BAQ4zDYEBDjMN</span></span> +<span class="line"><span style="color:#032F62">gQEOMg6BARAnF4EBJQYjgQEmBSOBASYFI4EBJgUjgQEmBSOBASYFI4EBJgUjgQEmBSOBASYFI4EBJgUj</span></span> +<span class="line"><span style="color:#032F62">gQEmBSOBAR0EBQUjgQEXFCOBARQZIYEBEh4egQERIRyBARAJDBAZgQEPBxARF4EBDgYSExWBAQ4FEwYD</span></span> +<span class="line"><span style="color:#032F62">CxSBAQ4FEwYFCxKBAQ0FFAYHChGBAQ0FFAYJCg+BAQ0FFAYKCg6BAQ0GEwYMCQ2BAQ4FEwYNCQyBAQ4G</span></span> +<span class="line"><span style="color:#032F62">EQYQBg2BAQ4HDwcRBQ2BAQ8IDAgSAw6BAQ8bFAEPgQERGCWBARIWJoEBFBIogQEXDSqBAU6BAU6BAU6B</span></span> +<span class="line"><span style="color:#032F62">AU6BAU6BAU6B0A=='</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#032F62">'0AFOgQFOgQFOgQFOgQFOgQFOgQEpBh+BASkGH4EBKQYfgQEqBR+BASoFH4EBKgUfgQEqBR+BASoFH4EB</span></span> +<span class="line"><span style="color:#032F62">KgUfgQEqBR+BARkuB4EBBkEHgQEHQAeBAQdAB4EBB0AHgQEHDBcFH4EBKgUfgQEqBR+BASoFH4EBKgUf</span></span> +<span class="line"><span style="color:#032F62">gQEqBR+BASoFH4EBKgUfgQEgDx+BAR4RH4EBHBMfgQEbFB+BARoIBAkfgQEZBwkGH4EBGQYLBh6BARgG</span></span> +<span class="line"><span style="color:#032F62">DQUegQEYBQ4GHYEBFwYPBR2BARcFEAUdgQEXBRAFHYEBFwUQBhyBARcFEAYcgQEXBQ8HHIEBFwUPBxyB</span></span> +<span class="line"><span style="color:#032F62">ARcGDgccgQEXBg0IHIEBGAYMBx2BARgHCggdgQEZCAYKHYEBGhcdgQEbFh2BARwVHYEBHgsBBh6BASAG</span></span> +<span class="line"><span style="color:#032F62">BAYegQEpBh+BASkGH4EBKAYggQEnByCBASYHIYEBJQcigQEkCCKBASIJI4EBIAokgQEeCyWBARwLJ4EB</span></span> +<span class="line"><span style="color:#032F62">GQ0ogQEWDiqBARcMK4EBGAktgQEZBTCBARoCMoEBToEBToEBToEBToEBToEBToHQ'</span><span style="color:#24292E">,];</span></span> +<span class="line"><span style="color:#24292E">$m</span><span style="color:#D73A49">=</span><span style="color:#032F62">""</span><span style="color:#24292E">;</span><span style="color:#D73A49">for</span><span style="color:#24292E">($k</span><span style="color:#D73A49">=</span><span style="color:#005CC5">0</span><span style="color:#24292E">;$k</span><span style="color:#D73A49"><</span><span style="color:#005CC5">min</span><span style="color:#24292E">(</span><span style="color:#005CC5">13</span><span style="color:#24292E">,</span><span style="color:#6F42C1">intdiv</span><span style="color:#24292E">(</span><span style="color:#005CC5">__LINE__</span><span style="color:#D73A49">-</span><span style="color:#005CC5">119</span><span style="color:#24292E">,</span><span style="color:#005CC5">80</span><span style="color:#24292E">)</span><span style="color:#D73A49">+</span><span style="color:#005CC5">1</span><span style="color:#24292E">);$k</span><span style="color:#D73A49">++</span><span style="color:#24292E">){$C</span><span style="color:#D73A49">=</span><span style="color:#005CC5">str_replace</span><span style="color:#24292E">(</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">""</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E">$c[$k]);$f</span><span style="color:#D73A49">=!</span><span style="color:#005CC5">0</span><span style="color:#24292E">;</span><span style="color:#D73A49">foreach</span><span style="color:#24292E">(</span><span style="color:#005CC5">str_split</span><span style="color:#24292E">(</span><span style="color:#005CC5">base64_decode</span><span style="color:#24292E">($C))</span><span style="color:#D73A49">as</span><span style="color:#24292E">$l){$L</span><span style="color:#D73A49">=</span><span style="color:#005CC5">ord</span><span style="color:#24292E">($l);$m</span><span style="color:#D73A49">.=</span><span style="color:#005CC5">str_repeat</span></span> +<span class="line"><span style="color:#24292E">($f</span><span style="color:#D73A49">?</span><span style="color:#032F62">"#"</span><span style="color:#D73A49">:</span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">32</span><span style="color:#24292E">),$L</span><span style="color:#D73A49">&</span><span style="color:#005CC5">127</span><span style="color:#24292E">);$f</span><span style="color:#D73A49">=!</span><span style="color:#24292E">$f;</span><span style="color:#D73A49">if</span><span style="color:#24292E">($L</span><span style="color:#D73A49">&</span><span style="color:#005CC5">128</span><span style="color:#24292E">){$m</span><span style="color:#D73A49">.=</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">;$f</span><span style="color:#D73A49">=!</span><span style="color:#005CC5">0</span><span style="color:#24292E">;</span><span style="color:#D73A49">continue</span><span style="color:#24292E">;}}}</span><span style="color:#005CC5">print</span><span style="color:#24292E">(</span></span> +<span class="line"><span style="color:#005CC5">str_replace</span><span style="color:#24292E">([</span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">96</span><span style="color:#24292E">),</span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">37</span><span style="color:#24292E">),</span><span style="color:#005CC5">chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">64</span><span style="color:#24292E">)],[</span><span style="color:#005CC5">implode</span><span style="color:#24292E">(</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#005CC5">array_map</span><span style="color:#24292E">(</span><span style="color:#D73A49">fn</span><span style="color:#24292E">($C)=></span><span style="color:#032F62">"'"</span><span style="color:#D73A49">.</span><span style="color:#005CC5">trim</span><span style="color:#24292E">(</span></span> +<span class="line"><span style="color:#005CC5">chunk_split</span><span style="color:#24292E">(</span><span style="color:#005CC5">str_replace</span><span style="color:#24292E">(</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">,</span><span style="color:#032F62">""</span><span style="color:#24292E">,$C),</span><span style="color:#005CC5">80</span><span style="color:#24292E">,</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">))</span><span style="color:#D73A49">.</span><span style="color:#032F62">"',"</span><span style="color:#24292E">,$c)),</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">{</span><span style="color:#24292E">$m</span><span style="color:#032F62">}"</span><span style="color:#24292E">,</span><span style="color:#032F62">"{</span><span style="color:#24292E">$s</span><span style="color:#032F62">}</span><span style="color:#005CC5">\n</span><span style="color:#032F62">Q;</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">],$s));</span></span></code></pre> + </div> </section> </div> </article> diff --git a/vhosts/blog/public/posts/2024-12-33/2024-reflections/index.html b/vhosts/blog/public/posts/2024-12-33/2024-reflections/index.html index f2169b2c..a6e0f3f6 100644 --- a/vhosts/blog/public/posts/2024-12-33/2024-reflections/index.html +++ b/vhosts/blog/public/posts/2024-12-33/2024-reflections/index.html @@ -13,8 +13,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>2024年の振り返り|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> diff --git a/vhosts/blog/public/posts/2025-01-08/phperkaigi-2023-tokens-q1/index.html b/vhosts/blog/public/posts/2025-01-08/phperkaigi-2023-tokens-q1/index.html index 16bf6730..892c7f34 100644 --- a/vhosts/blog/public/posts/2025-01-08/phperkaigi-2023-tokens-q1/index.html +++ b/vhosts/blog/public/posts/2025-01-08/phperkaigi-2023-tokens-q1/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>PHPerKaigi 2023 トークン問題解説 (1/5)|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -136,7 +135,9 @@ まずはトークンを得る方法を解説抜きで説明する。次のように実行する。 </p> - <pre class="highlight"><code>$ echo "#iwillblog" | php Q1.png >/dev/null</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ echo "#iwillblog" | php Q1.png >/dev/null</span></span></code></pre> + </div> <p> 無事に実行できていれば「#ModernPHPisStaticallyTypedLanguage」というトークンが得られる。 @@ -151,7 +152,9 @@ まずは素直に画像として見てみよう。全体は QR コードになっている。適当な QR コードリーダで読み込むと、次のようなテキストが表示されるはずだ。 </p> - <pre class="highlight"><code>Guess password. $ echo "password" | php Q1.png >/dev/null</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>Guess password. $ echo "password" | php Q1.png >/dev/null</span></span></code></pre> + </div> <p> メッセージは、この画像の実行方法とこの問題でやるべきこと (パスワードの推測) を示している。 @@ -168,8 +171,10 @@ 不正なパスワードを使って実行してみると、次のようなエラーメッセージが表示される。 </p> - <pre class="highlight"><code>$ echo "foo" | php Q1.png >/dev/null -401 Unauthorized</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ echo "foo" | php Q1.png >/dev/null</span></span> +<span class="line"><span>401 Unauthorized</span></span></code></pre> + </div> <p> すでに<a href="#section--how-to-solve">「解き方」の節</a>で示したように、パスワードである PHPer トークンは「#iwillblog」である。これを与えて実行すると正解のトークンが得られる。 @@ -258,23 +263,27 @@ <code>strings</code> コマンドを使うと、隠されたデータを簡単に閲覧できる。 </p> - <pre class="highlight"><code>IHDR --HHc -<PLTE -IDATx -IEND -<?php -error_reporting(-1); -$b = unpack('C*', file_get_contents(__FILE__)); -$w = $b[20]+2; -$h = $b[24]+2; -// (以下略)</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>IHDR</span></span> +<span class="line"><span>-HHc</span></span> +<span class="line"><span><PLTE</span></span> +<span class="line"><span>IDATx</span></span> +<span class="line"><span>IEND</span></span> +<span class="line"><span><?php</span></span> +<span class="line"><span>error_reporting(-1);</span></span> +<span class="line"><span>$b = unpack('C*', file_get_contents(__FILE__));</span></span> +<span class="line"><span>$w = $b[20]+2;</span></span> +<span class="line"><span>$h = $b[24]+2;</span></span> +<span class="line"><span>// (以下略)</span></span></code></pre> + </div> <p> <code>IHDR</code> や <code>IEND</code> が PNG 画像の一部で、<code><?php</code> からが実際のプログラムになっている。もちろんこれを PHP プログラムとして動かすと、PHP タグより前にある PNG 画像としてのデータはそのまま標準出力へと出力されてしまう。それを防ぐため、QR コードを読み込んだときの実行方法 </p> - <pre class="highlight"><code>Guess password. $ echo "password" | php Q1.png >/dev/null</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>Guess password. $ echo "password" | php Q1.png >/dev/null</span></span></code></pre> + </div> <p> には標準出力を捨てるよう <code>>/dev/null</code> と指定されている。 @@ -291,107 +300,109 @@ $h = $b[24]+2; 画像の正体がわかったところで、画像に隠されていた PHP プログラムについて見ていこう。先ほどは一部しか記載しなかったので、全体を載せる。なお、ある程度ゴルフしながら書いたので、空白こそ残しているものの可読性は非常に低いことと思う。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta"><?php</span> -<span class="hljs-title function_ invoke__">error_reporting</span>(-<span class="hljs-number">1</span>); -<span class="hljs-variable">$b</span> = <span class="hljs-title function_ invoke__">unpack</span>(<span class="hljs-string">'C*'</span>, <span class="hljs-title function_ invoke__">file_get_contents</span>(<span class="hljs-keyword">__FILE__</span>)); -<span class="hljs-variable">$w</span> = <span class="hljs-variable">$b</span>[<span class="hljs-number">20</span>]+<span class="hljs-number">2</span>; -<span class="hljs-variable">$h</span> = <span class="hljs-variable">$b</span>[<span class="hljs-number">24</span>]+<span class="hljs-number">2</span>; -<span class="hljs-variable">$cs</span> = []; -<span class="hljs-keyword">for</span> (<span class="hljs-variable">$y</span> = <span class="hljs-number">0</span>; <span class="hljs-variable">$y</span> < <span class="hljs-variable">$h</span>; <span class="hljs-variable">$y</span>++) - <span class="hljs-keyword">for</span> (<span class="hljs-variable">$x</span> = <span class="hljs-number">0</span>; <span class="hljs-variable">$x</span> < <span class="hljs-variable">$w</span>; <span class="hljs-variable">$x</span>++) - <span class="hljs-variable">$cs</span>[<span class="hljs-variable">$y</span>*<span class="hljs-variable">$w</span> + <span class="hljs-variable">$x</span>] = (<span class="hljs-variable">$x</span>*<span class="hljs-variable">$y</span> === <span class="hljs-number">0</span> || <span class="hljs-variable">$x</span> === <span class="hljs-variable">$w</span>-<span class="hljs-number">1</span> || <span class="hljs-variable">$y</span> === <span class="hljs-variable">$h</span>-<span class="hljs-number">1</span>) - ? <span class="hljs-number">0</span> - : <span class="hljs-variable">$b</span>[<span class="hljs-number">122</span>+(<span class="hljs-variable">$y</span>-<span class="hljs-number">1</span>)*(<span class="hljs-variable">$w</span>-<span class="hljs-number">1</span>)+<span class="hljs-variable">$x</span>-<span class="hljs-number">1</span>]; -<span class="hljs-variable">$i</span> = <span class="hljs-title function_ invoke__">stream_isatty</span>(STDIN) - ? [] - : <span class="hljs-title function_ invoke__">array_map</span>(<span class="hljs-title function_ invoke__">ord</span>(...), <span class="hljs-title function_ invoke__">str_split</span>(<span class="hljs-title function_ invoke__">trim</span>((<span class="hljs-keyword">string</span>) <span class="hljs-title function_ invoke__">fgets</span>(STDIN)))); -<span class="hljs-variable">$m</span> = []; -<span class="hljs-variable">$pc</span> = <span class="hljs-number">1</span>*<span class="hljs-variable">$w</span>+<span class="hljs-number">1</span>; -<span class="hljs-variable">$dp</span> = <span class="hljs-number">0</span>; -<span class="hljs-variable">$cc</span> = <span class="hljs-number">1</span>; -<span class="hljs-variable">$c0</span> = <span class="hljs-number">1</span>; -<span class="hljs-variable">$b</span> = <span class="hljs-number">0</span>; -<span class="hljs-variable">$ns</span> = <span class="hljs-number">0</span>; -<span class="hljs-variable">$o</span> = <span class="hljs-string">''</span>; -<span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>) { - <span class="hljs-variable">$ns</span>++; - <span class="hljs-keyword">if</span> (<span class="hljs-variable">$ns</span> > <span class="hljs-number">1e5</span>) { - <span class="hljs-keyword">echo</span> <span class="hljs-string">"infinite loop detected\n"</span>; - <span class="hljs-keyword">break</span>; - <span class="hljs-variable">$c1</span> = <span class="hljs-variable">$cs</span>[<span class="hljs-variable">$pc</span>]; - <span class="hljs-variable">$y</span> = (<span class="hljs-number">6</span> + <span class="hljs-title function_ invoke__">intdiv</span>(<span class="hljs-variable">$c1</span>-<span class="hljs-number">2</span>, <span class="hljs-number">3</span>) - <span class="hljs-title function_ invoke__">intdiv</span>(<span class="hljs-variable">$c0</span>-<span class="hljs-number">2</span>, <span class="hljs-number">3</span>)) % <span class="hljs-number">6</span>; - <span class="hljs-variable">$x</span> = (<span class="hljs-number">3</span> + <span class="hljs-variable">$c1</span>%<span class="hljs-number">3</span> - <span class="hljs-variable">$c0</span>%<span class="hljs-number">3</span>) % <span class="hljs-number">3</span>; - <span class="hljs-keyword">match</span> ((<span class="hljs-variable">$c0</span> !== <span class="hljs-number">1</span>) * (<span class="hljs-variable">$c1</span> !== <span class="hljs-number">1</span>) * (<span class="hljs-variable">$y</span>*<span class="hljs-number">3</span> + <span class="hljs-variable">$x</span>)) { - <span class="hljs-number">1</span> => <span class="hljs-variable">$m</span>[] = <span class="hljs-variable">$b</span>, - <span class="hljs-number">2</span> => <span class="hljs-title function_ invoke__">array_pop</span>(<span class="hljs-variable">$m</span>), - <span class="hljs-number">3</span> => <span class="hljs-variable">$m</span>[] = <span class="hljs-title function_ invoke__">array_pop</span>(<span class="hljs-variable">$m</span>) + <span class="hljs-title function_ invoke__">array_pop</span>(<span class="hljs-variable">$m</span>), - <span class="hljs-number">4</span> => <span class="hljs-variable">$m</span>[] = (<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$x</span>, <span class="hljs-variable">$y</span></span>) =></span> <span class="hljs-variable">$y</span> - <span class="hljs-variable">$x</span>)(<span class="hljs-title function_ invoke__">array_pop</span>(<span class="hljs-variable">$m</span>), <span class="hljs-title function_ invoke__">array_pop</span>(<span class="hljs-variable">$m</span>)), - <span class="hljs-number">5</span> => <span class="hljs-variable">$m</span>[] = <span class="hljs-title function_ invoke__">array_pop</span>(<span class="hljs-variable">$m</span>) * <span class="hljs-title function_ invoke__">array_pop</span>(<span class="hljs-variable">$m</span>), - <span class="hljs-number">8</span> => <span class="hljs-variable">$m</span>[] = <span class="hljs-title function_ invoke__">array_pop</span>(<span class="hljs-variable">$m</span>) === <span class="hljs-number">0</span> ? <span class="hljs-number">1</span> : <span class="hljs-number">0</span>, - <span class="hljs-number">11</span> => <span class="hljs-variable">$cc</span> *= <span class="hljs-title function_ invoke__">pow</span>(-<span class="hljs-number">1</span>, <span class="hljs-title function_ invoke__">array_pop</span>(<span class="hljs-variable">$m</span>)), - <span class="hljs-number">12</span> => <span class="hljs-variable">$m</span>[] = <span class="hljs-variable">$m</span>[<span class="hljs-title function_ invoke__">count</span>(<span class="hljs-variable">$m</span>)-<span class="hljs-number">1</span>], - <span class="hljs-number">13</span> => <span class="hljs-variable">$m</span> = (<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-variable">$n</span>, <span class="hljs-variable">$d</span>, <span class="hljs-variable">$m</span>, <span class="hljs-variable">$l</span></span>) =></span> [ - ...<span class="hljs-title function_ invoke__">array_slice</span>(<span class="hljs-variable">$m</span>, <span class="hljs-number">0</span>, <span class="hljs-variable">$l</span>-<span class="hljs-variable">$d</span>), - ...<span class="hljs-title function_ invoke__">array_reverse</span>([ - ...<span class="hljs-title function_ invoke__">array_reverse</span>(<span class="hljs-title function_ invoke__">array_slice</span>(<span class="hljs-variable">$m</span>, <span class="hljs-variable">$l</span>-<span class="hljs-variable">$d</span>, <span class="hljs-variable">$d</span>-<span class="hljs-variable">$n</span>)), - ...<span class="hljs-title function_ invoke__">array_reverse</span>(<span class="hljs-title function_ invoke__">array_slice</span>(<span class="hljs-variable">$m</span>, <span class="hljs-variable">$l</span>-<span class="hljs-variable">$n</span>)), - ]), - ])(<span class="hljs-title function_ invoke__">array_pop</span>(<span class="hljs-variable">$m</span>), <span class="hljs-title function_ invoke__">array_pop</span>(<span class="hljs-variable">$m</span>), <span class="hljs-variable">$m</span>, <span class="hljs-title function_ invoke__">count</span>(<span class="hljs-variable">$m</span>)), - <span class="hljs-number">15</span> => !<span class="hljs-keyword">empty</span>(<span class="hljs-variable">$i</span>) <span class="hljs-keyword">and</span> <span class="hljs-variable">$m</span>[] = <span class="hljs-title function_ invoke__">array_shift</span>(<span class="hljs-variable">$i</span>), - <span class="hljs-number">16</span> => <span class="hljs-variable">$o</span> .= <span class="hljs-title function_ invoke__">sprintf</span>(<span class="hljs-string">'%d'</span>, <span class="hljs-title function_ invoke__">array_pop</span>(<span class="hljs-variable">$m</span>)), - <span class="hljs-number">17</span> => <span class="hljs-variable">$o</span> .= <span class="hljs-title function_ invoke__">sprintf</span>(<span class="hljs-string">'%c'</span>, <span class="hljs-title function_ invoke__">array_pop</span>(<span class="hljs-variable">$m</span>)), - <span class="hljs-keyword">default</span> => <span class="hljs-string">'nop'</span>, - }; - <span class="hljs-variable">$c0</span> = <span class="hljs-variable">$c1</span>; - <span class="hljs-keyword">for</span> (<span class="hljs-variable">$j</span> = <span class="hljs-number">0</span>; <span class="hljs-variable">$j</span> < <span class="hljs-number">8</span>; <span class="hljs-variable">$j</span>++) { - <span class="hljs-variable">$v</span> = []; - <span class="hljs-keyword">if</span> (<span class="hljs-variable">$c1</span> === <span class="hljs-number">1</span>) { - <span class="hljs-variable">$x</span> = <span class="hljs-variable">$pc</span> % <span class="hljs-variable">$w</span>; - <span class="hljs-variable">$y</span> = <span class="hljs-title function_ invoke__">intdiv</span>(<span class="hljs-variable">$pc</span>, <span class="hljs-variable">$w</span>); - <span class="hljs-variable">$e</span> = [(<span class="hljs-variable">$y</span>+<span class="hljs-number">1</span>)*<span class="hljs-variable">$w</span>-<span class="hljs-number">1</span>, (<span class="hljs-variable">$h</span>-<span class="hljs-number">1</span>)*<span class="hljs-variable">$w</span>+<span class="hljs-variable">$x</span>, <span class="hljs-variable">$y</span>*<span class="hljs-variable">$w</span>, <span class="hljs-variable">$x</span>][<span class="hljs-variable">$dp</span>]; - <span class="hljs-variable">$z</span> = [<span class="hljs-number">1</span>, <span class="hljs-variable">$w</span>, -<span class="hljs-number">1</span>, -<span class="hljs-variable">$w</span>][<span class="hljs-variable">$dp</span>]; - <span class="hljs-keyword">for</span> (<span class="hljs-variable">$ep</span> = <span class="hljs-variable">$pc</span>; <span class="hljs-variable">$ep</span> !== <span class="hljs-variable">$e</span>; <span class="hljs-variable">$ep</span> += <span class="hljs-variable">$z</span>) - <span class="hljs-keyword">if</span> (<span class="hljs-variable">$cs</span>[<span class="hljs-variable">$ep</span>] !== <span class="hljs-number">1</span>) <span class="hljs-keyword">break</span>; - <span class="hljs-variable">$ep</span> -= <span class="hljs-variable">$z</span>; - <span class="hljs-variable">$pc</span> = <span class="hljs-variable">$ep</span>; - } <span class="hljs-keyword">else</span> { - <span class="hljs-variable">$q</span> = [<span class="hljs-variable">$pc</span>]; - <span class="hljs-variable">$ep</span> = <span class="hljs-variable">$pc</span>; - <span class="hljs-keyword">while</span> (!<span class="hljs-keyword">empty</span>(<span class="hljs-variable">$q</span>)) { - <span class="hljs-variable">$qq</span> = <span class="hljs-title function_ invoke__">array_pop</span>(<span class="hljs-variable">$q</span>); - <span class="hljs-variable">$v</span>[<span class="hljs-variable">$qq</span>] = <span class="hljs-literal">true</span>; - <span class="hljs-keyword">foreach</span> ([<span class="hljs-variable">$qq</span>+<span class="hljs-number">1</span>, <span class="hljs-variable">$qq</span>+<span class="hljs-variable">$w</span>, <span class="hljs-variable">$qq</span>-<span class="hljs-number">1</span>, <span class="hljs-variable">$qq</span>-<span class="hljs-variable">$w</span>] <span class="hljs-keyword">as</span> <span class="hljs-variable">$qp</span>) { - <span class="hljs-keyword">if</span> (<span class="hljs-variable">$cs</span>[<span class="hljs-variable">$qp</span>] !== <span class="hljs-variable">$c1</span>) <span class="hljs-keyword">continue</span>; - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$v</span>[<span class="hljs-variable">$qp</span>])) <span class="hljs-keyword">continue</span>; - <span class="hljs-variable">$q</span>[] = <span class="hljs-variable">$qp</span>; - <span class="hljs-variable">$qx</span> = <span class="hljs-variable">$qp</span> % <span class="hljs-variable">$w</span>; - <span class="hljs-variable">$qy</span> = <span class="hljs-title function_ invoke__">intdiv</span>(<span class="hljs-variable">$qp</span>, <span class="hljs-variable">$w</span>); - <span class="hljs-variable">$x</span> = <span class="hljs-variable">$ep</span> % <span class="hljs-variable">$w</span>; - <span class="hljs-variable">$y</span> = <span class="hljs-title function_ invoke__">intdiv</span>(<span class="hljs-variable">$ep</span>, <span class="hljs-variable">$w</span>); - <span class="hljs-keyword">if</span> ( - (<span class="hljs-variable">$dp</span> === <span class="hljs-number">0</span> && (<span class="hljs-variable">$x</span> < <span class="hljs-variable">$qx</span> || (<span class="hljs-variable">$x</span> === <span class="hljs-variable">$qx</span> && (<span class="hljs-variable">$y</span><=><span class="hljs-variable">$qy</span>) === <span class="hljs-variable">$cc</span>))) - || (<span class="hljs-variable">$dp</span> === <span class="hljs-number">1</span> && (<span class="hljs-variable">$y</span> < <span class="hljs-variable">$qy</span> || (<span class="hljs-variable">$y</span> === <span class="hljs-variable">$qy</span> && (<span class="hljs-variable">$qx</span><=><span class="hljs-variable">$x</span>) === <span class="hljs-variable">$cc</span>))) - || (<span class="hljs-variable">$dp</span> === <span class="hljs-number">2</span> && (<span class="hljs-variable">$qx</span> < <span class="hljs-variable">$x</span> || (<span class="hljs-variable">$qx</span> === <span class="hljs-variable">$x</span> && (<span class="hljs-variable">$qy</span><=><span class="hljs-variable">$y</span>) === <span class="hljs-variable">$cc</span>))) - || (<span class="hljs-variable">$dp</span> === <span class="hljs-number">3</span> && (<span class="hljs-variable">$qy</span> < <span class="hljs-variable">$y</span> || (<span class="hljs-variable">$qy</span> === <span class="hljs-variable">$y</span> && (<span class="hljs-variable">$x</span><=><span class="hljs-variable">$qx</span>) === <span class="hljs-variable">$cc</span>))) - ) - <span class="hljs-variable">$ep</span> = <span class="hljs-variable">$qp</span>; - } - } - } - <span class="hljs-variable">$np</span> = <span class="hljs-variable">$ep</span> + [<span class="hljs-number">1</span>, <span class="hljs-variable">$w</span>, -<span class="hljs-number">1</span>, -<span class="hljs-variable">$w</span>][<span class="hljs-variable">$dp</span>]; - <span class="hljs-keyword">if</span> (<span class="hljs-variable">$cs</span>[<span class="hljs-variable">$np</span>] !== <span class="hljs-number">0</span>) { - <span class="hljs-variable">$b</span> = <span class="hljs-title function_ invoke__">count</span>(<span class="hljs-title function_ invoke__">array_keys</span>(<span class="hljs-variable">$v</span>)); - <span class="hljs-variable">$pc</span> = <span class="hljs-variable">$np</span>; - <span class="hljs-keyword">break</span>; - } - <span class="hljs-keyword">if</span> (<span class="hljs-variable">$j</span> === <span class="hljs-number">7</span>) <span class="hljs-keyword">break</span> <span class="hljs-number">2</span>; - <span class="hljs-keyword">if</span> (<span class="hljs-variable">$j</span> % <span class="hljs-number">2</span> === <span class="hljs-number">0</span>) <span class="hljs-variable">$cc</span> = -<span class="hljs-variable">$cc</span>; - <span class="hljs-keyword">if</span> (<span class="hljs-variable">$j</span> % <span class="hljs-number">2</span> === <span class="hljs-number">1</span>) <span class="hljs-variable">$dp</span> = (<span class="hljs-variable">$dp</span>+<span class="hljs-number">1</span>) % <span class="hljs-number">4</span>; -<span class="hljs-comment">// The original Piet image is wrong: it outputs 403 error for invalid passwords.</span> -<span class="hljs-comment">// Failure of authentication should be notified by 401, not 403.</span> -<span class="hljs-comment">// I noticed that one month before PHPerKaigi, but I could not read or write (paint)</span> -<span class="hljs-comment">// Piet any longer at that time.</span> -<span class="hljs-title function_ invoke__">fwrite</span>(STDERR, <span class="hljs-title function_ invoke__">str_replace</span>(<span class="hljs-string">'403 Forbidden'</span>, <span class="hljs-string">'401 Unauthorized'</span>, <span class="hljs-variable">$o</span>));</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> +<span class="line"><span style="color:#005CC5">error_reporting</span><span style="color:#24292E">(</span><span style="color:#D73A49">-</span><span style="color:#005CC5">1</span><span style="color:#24292E">);</span></span> +<span class="line"><span style="color:#24292E">$b </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> unpack</span><span style="color:#24292E">(</span><span style="color:#032F62">'C*'</span><span style="color:#24292E">, </span><span style="color:#005CC5">file_get_contents</span><span style="color:#24292E">(</span><span style="color:#005CC5">__FILE__</span><span style="color:#24292E">));</span></span> +<span class="line"><span style="color:#24292E">$w </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $b[</span><span style="color:#005CC5">20</span><span style="color:#24292E">]</span><span style="color:#D73A49">+</span><span style="color:#005CC5">2</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$h </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $b[</span><span style="color:#005CC5">24</span><span style="color:#24292E">]</span><span style="color:#D73A49">+</span><span style="color:#005CC5">2</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$cs </span><span style="color:#D73A49">=</span><span style="color:#24292E"> [];</span></span> +<span class="line"><span style="color:#D73A49">for</span><span style="color:#24292E"> ($y </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">; $y </span><span style="color:#D73A49"><</span><span style="color:#24292E"> $h; $y</span><span style="color:#D73A49">++</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#D73A49"> for</span><span style="color:#24292E"> ($x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">; $x </span><span style="color:#D73A49"><</span><span style="color:#24292E"> $w; $x</span><span style="color:#D73A49">++</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#24292E"> $cs[$y</span><span style="color:#D73A49">*</span><span style="color:#24292E">$w </span><span style="color:#D73A49">+</span><span style="color:#24292E"> $x] </span><span style="color:#D73A49">=</span><span style="color:#24292E"> ($x</span><span style="color:#D73A49">*</span><span style="color:#24292E">$y </span><span style="color:#D73A49">===</span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> ||</span><span style="color:#24292E"> $x </span><span style="color:#D73A49">===</span><span style="color:#24292E"> $w</span><span style="color:#D73A49">-</span><span style="color:#005CC5">1</span><span style="color:#D73A49"> ||</span><span style="color:#24292E"> $y </span><span style="color:#D73A49">===</span><span style="color:#24292E"> $h</span><span style="color:#D73A49">-</span><span style="color:#005CC5">1</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#D73A49"> ?</span><span style="color:#005CC5"> 0</span></span> +<span class="line"><span style="color:#D73A49"> :</span><span style="color:#24292E"> $b[</span><span style="color:#005CC5">122</span><span style="color:#D73A49">+</span><span style="color:#24292E">($y</span><span style="color:#D73A49">-</span><span style="color:#005CC5">1</span><span style="color:#24292E">)</span><span style="color:#D73A49">*</span><span style="color:#24292E">($w</span><span style="color:#D73A49">-</span><span style="color:#005CC5">1</span><span style="color:#24292E">)</span><span style="color:#D73A49">+</span><span style="color:#24292E">$x</span><span style="color:#D73A49">-</span><span style="color:#005CC5">1</span><span style="color:#24292E">];</span></span> +<span class="line"><span style="color:#24292E">$i </span><span style="color:#D73A49">=</span><span style="color:#6F42C1"> stream_isatty</span><span style="color:#24292E">(</span><span style="color:#005CC5">STDIN</span><span style="color:#24292E">)</span></span> +<span class="line"><span style="color:#D73A49"> ?</span><span style="color:#24292E"> []</span></span> +<span class="line"><span style="color:#D73A49"> :</span><span style="color:#005CC5"> array_map</span><span style="color:#24292E">(</span><span style="color:#005CC5">ord</span><span style="color:#24292E">(</span><span style="color:#D73A49">...</span><span style="color:#24292E">), </span><span style="color:#005CC5">str_split</span><span style="color:#24292E">(</span><span style="color:#005CC5">trim</span><span style="color:#24292E">((</span><span style="color:#D73A49">string</span><span style="color:#24292E">) </span><span style="color:#005CC5">fgets</span><span style="color:#24292E">(</span><span style="color:#005CC5">STDIN</span><span style="color:#24292E">))));</span></span> +<span class="line"><span style="color:#24292E">$m </span><span style="color:#D73A49">=</span><span style="color:#24292E"> [];</span></span> +<span class="line"><span style="color:#24292E">$pc </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> 1</span><span style="color:#D73A49">*</span><span style="color:#24292E">$w</span><span style="color:#D73A49">+</span><span style="color:#005CC5">1</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$dp </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$cc </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> 1</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$c0 </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> 1</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$b </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$ns </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E">$o </span><span style="color:#D73A49">=</span><span style="color:#032F62"> ''</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49">while</span><span style="color:#24292E"> (</span><span style="color:#005CC5">true</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#24292E"> $ns</span><span style="color:#D73A49">++</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> ($ns </span><span style="color:#D73A49">></span><span style="color:#005CC5"> 1e5</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#005CC5"> echo</span><span style="color:#032F62"> "infinite loop detected</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49"> break</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E"> $c1 </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $cs[$pc];</span></span> +<span class="line"><span style="color:#24292E"> $y </span><span style="color:#D73A49">=</span><span style="color:#24292E"> (</span><span style="color:#005CC5">6</span><span style="color:#D73A49"> +</span><span style="color:#6F42C1"> intdiv</span><span style="color:#24292E">($c1</span><span style="color:#D73A49">-</span><span style="color:#005CC5">2</span><span style="color:#24292E">, </span><span style="color:#005CC5">3</span><span style="color:#24292E">) </span><span style="color:#D73A49">-</span><span style="color:#6F42C1"> intdiv</span><span style="color:#24292E">($c0</span><span style="color:#D73A49">-</span><span style="color:#005CC5">2</span><span style="color:#24292E">, </span><span style="color:#005CC5">3</span><span style="color:#24292E">)) </span><span style="color:#D73A49">%</span><span style="color:#005CC5"> 6</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E"> $x </span><span style="color:#D73A49">=</span><span style="color:#24292E"> (</span><span style="color:#005CC5">3</span><span style="color:#D73A49"> +</span><span style="color:#24292E"> $c1</span><span style="color:#D73A49">%</span><span style="color:#005CC5">3</span><span style="color:#D73A49"> -</span><span style="color:#24292E"> $c0</span><span style="color:#D73A49">%</span><span style="color:#005CC5">3</span><span style="color:#24292E">) </span><span style="color:#D73A49">%</span><span style="color:#005CC5"> 3</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49"> match</span><span style="color:#24292E"> (($c0 </span><span style="color:#D73A49">!==</span><span style="color:#005CC5"> 1</span><span style="color:#24292E">) </span><span style="color:#D73A49">*</span><span style="color:#24292E"> ($c1 </span><span style="color:#D73A49">!==</span><span style="color:#005CC5"> 1</span><span style="color:#24292E">) </span><span style="color:#D73A49">*</span><span style="color:#24292E"> ($y</span><span style="color:#D73A49">*</span><span style="color:#005CC5">3</span><span style="color:#D73A49"> +</span><span style="color:#24292E"> $x)) {</span></span> +<span class="line"><span style="color:#005CC5"> 1</span><span style="color:#D73A49"> =></span><span style="color:#24292E"> $m[] </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $b,</span></span> +<span class="line"><span style="color:#005CC5"> 2</span><span style="color:#D73A49"> =></span><span style="color:#005CC5"> array_pop</span><span style="color:#24292E">($m),</span></span> +<span class="line"><span style="color:#005CC5"> 3</span><span style="color:#D73A49"> =></span><span style="color:#24292E"> $m[] </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> array_pop</span><span style="color:#24292E">($m) </span><span style="color:#D73A49">+</span><span style="color:#005CC5"> array_pop</span><span style="color:#24292E">($m),</span></span> +<span class="line"><span style="color:#005CC5"> 4</span><span style="color:#D73A49"> =></span><span style="color:#24292E"> $m[] </span><span style="color:#D73A49">=</span><span style="color:#24292E"> (</span><span style="color:#D73A49">fn</span><span style="color:#24292E">($x, $y) => $y </span><span style="color:#D73A49">-</span><span style="color:#24292E"> $x)(</span><span style="color:#005CC5">array_pop</span><span style="color:#24292E">($m), </span><span style="color:#005CC5">array_pop</span><span style="color:#24292E">($m)),</span></span> +<span class="line"><span style="color:#005CC5"> 5</span><span style="color:#D73A49"> =></span><span style="color:#24292E"> $m[] </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> array_pop</span><span style="color:#24292E">($m) </span><span style="color:#D73A49">*</span><span style="color:#005CC5"> array_pop</span><span style="color:#24292E">($m),</span></span> +<span class="line"><span style="color:#005CC5"> 8</span><span style="color:#D73A49"> =></span><span style="color:#24292E"> $m[] </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> array_pop</span><span style="color:#24292E">($m) </span><span style="color:#D73A49">===</span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> ?</span><span style="color:#005CC5"> 1</span><span style="color:#D73A49"> :</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#005CC5"> 11</span><span style="color:#D73A49"> =></span><span style="color:#24292E"> $cc </span><span style="color:#D73A49">*=</span><span style="color:#005CC5"> pow</span><span style="color:#24292E">(</span><span style="color:#D73A49">-</span><span style="color:#005CC5">1</span><span style="color:#24292E">, </span><span style="color:#005CC5">array_pop</span><span style="color:#24292E">($m)),</span></span> +<span class="line"><span style="color:#005CC5"> 12</span><span style="color:#D73A49"> =></span><span style="color:#24292E"> $m[] </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $m[</span><span style="color:#005CC5">count</span><span style="color:#24292E">($m)</span><span style="color:#D73A49">-</span><span style="color:#005CC5">1</span><span style="color:#24292E">],</span></span> +<span class="line"><span style="color:#005CC5"> 13</span><span style="color:#D73A49"> =></span><span style="color:#24292E"> $m </span><span style="color:#D73A49">=</span><span style="color:#24292E"> (</span><span style="color:#D73A49">fn</span><span style="color:#24292E">($n, $d, $m, $l) => [</span></span> +<span class="line"><span style="color:#D73A49"> ...</span><span style="color:#005CC5">array_slice</span><span style="color:#24292E">($m, </span><span style="color:#005CC5">0</span><span style="color:#24292E">, $l</span><span style="color:#D73A49">-</span><span style="color:#24292E">$d),</span></span> +<span class="line"><span style="color:#D73A49"> ...</span><span style="color:#005CC5">array_reverse</span><span style="color:#24292E">([</span></span> +<span class="line"><span style="color:#D73A49"> ...</span><span style="color:#005CC5">array_reverse</span><span style="color:#24292E">(</span><span style="color:#005CC5">array_slice</span><span style="color:#24292E">($m, $l</span><span style="color:#D73A49">-</span><span style="color:#24292E">$d, $d</span><span style="color:#D73A49">-</span><span style="color:#24292E">$n)),</span></span> +<span class="line"><span style="color:#D73A49"> ...</span><span style="color:#005CC5">array_reverse</span><span style="color:#24292E">(</span><span style="color:#005CC5">array_slice</span><span style="color:#24292E">($m, $l</span><span style="color:#D73A49">-</span><span style="color:#24292E">$n)),</span></span> +<span class="line"><span style="color:#24292E"> ]),</span></span> +<span class="line"><span style="color:#24292E"> ])(</span><span style="color:#005CC5">array_pop</span><span style="color:#24292E">($m), </span><span style="color:#005CC5">array_pop</span><span style="color:#24292E">($m), $m, </span><span style="color:#005CC5">count</span><span style="color:#24292E">($m)),</span></span> +<span class="line"><span style="color:#005CC5"> 15</span><span style="color:#D73A49"> =></span><span style="color:#D73A49"> !</span><span style="color:#005CC5">empty</span><span style="color:#24292E">($i) </span><span style="color:#D73A49">and</span><span style="color:#24292E"> $m[] </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> array_shift</span><span style="color:#24292E">($i),</span></span> +<span class="line"><span style="color:#005CC5"> 16</span><span style="color:#D73A49"> =></span><span style="color:#24292E"> $o </span><span style="color:#D73A49">.=</span><span style="color:#005CC5"> sprintf</span><span style="color:#24292E">(</span><span style="color:#032F62">'%d'</span><span style="color:#24292E">, </span><span style="color:#005CC5">array_pop</span><span style="color:#24292E">($m)),</span></span> +<span class="line"><span style="color:#005CC5"> 17</span><span style="color:#D73A49"> =></span><span style="color:#24292E"> $o </span><span style="color:#D73A49">.=</span><span style="color:#005CC5"> sprintf</span><span style="color:#24292E">(</span><span style="color:#032F62">'%c'</span><span style="color:#24292E">, </span><span style="color:#005CC5">array_pop</span><span style="color:#24292E">($m)),</span></span> +<span class="line"><span style="color:#D73A49"> default</span><span style="color:#D73A49"> =></span><span style="color:#032F62"> 'nop'</span><span style="color:#24292E">,</span></span> +<span class="line"><span style="color:#24292E"> };</span></span> +<span class="line"><span style="color:#24292E"> $c0 </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $c1;</span></span> +<span class="line"><span style="color:#D73A49"> for</span><span style="color:#24292E"> ($j </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">; $j </span><span style="color:#D73A49"><</span><span style="color:#005CC5"> 8</span><span style="color:#24292E">; $j</span><span style="color:#D73A49">++</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#24292E"> $v </span><span style="color:#D73A49">=</span><span style="color:#24292E"> [];</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> ($c1 </span><span style="color:#D73A49">===</span><span style="color:#005CC5"> 1</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#24292E"> $x </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $pc </span><span style="color:#D73A49">%</span><span style="color:#24292E"> $w;</span></span> +<span class="line"><span style="color:#24292E"> $y </span><span style="color:#D73A49">=</span><span style="color:#6F42C1"> intdiv</span><span style="color:#24292E">($pc, $w);</span></span> +<span class="line"><span style="color:#24292E"> $e </span><span style="color:#D73A49">=</span><span style="color:#24292E"> [($y</span><span style="color:#D73A49">+</span><span style="color:#005CC5">1</span><span style="color:#24292E">)</span><span style="color:#D73A49">*</span><span style="color:#24292E">$w</span><span style="color:#D73A49">-</span><span style="color:#005CC5">1</span><span style="color:#24292E">, ($h</span><span style="color:#D73A49">-</span><span style="color:#005CC5">1</span><span style="color:#24292E">)</span><span style="color:#D73A49">*</span><span style="color:#24292E">$w</span><span style="color:#D73A49">+</span><span style="color:#24292E">$x, $y</span><span style="color:#D73A49">*</span><span style="color:#24292E">$w, $x][$dp];</span></span> +<span class="line"><span style="color:#24292E"> $z </span><span style="color:#D73A49">=</span><span style="color:#24292E"> [</span><span style="color:#005CC5">1</span><span style="color:#24292E">, $w, </span><span style="color:#D73A49">-</span><span style="color:#005CC5">1</span><span style="color:#24292E">, </span><span style="color:#D73A49">-</span><span style="color:#24292E">$w][$dp];</span></span> +<span class="line"><span style="color:#D73A49"> for</span><span style="color:#24292E"> ($ep </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $pc; $ep </span><span style="color:#D73A49">!==</span><span style="color:#24292E"> $e; $ep </span><span style="color:#D73A49">+=</span><span style="color:#24292E"> $z)</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> ($cs[$ep] </span><span style="color:#D73A49">!==</span><span style="color:#005CC5"> 1</span><span style="color:#24292E">) </span><span style="color:#D73A49">break</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E"> $ep </span><span style="color:#D73A49">-=</span><span style="color:#24292E"> $z;</span></span> +<span class="line"><span style="color:#24292E"> $pc </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $ep;</span></span> +<span class="line"><span style="color:#24292E"> } </span><span style="color:#D73A49">else</span><span style="color:#24292E"> {</span></span> +<span class="line"><span style="color:#24292E"> $q </span><span style="color:#D73A49">=</span><span style="color:#24292E"> [$pc];</span></span> +<span class="line"><span style="color:#24292E"> $ep </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $pc;</span></span> +<span class="line"><span style="color:#D73A49"> while</span><span style="color:#24292E"> (</span><span style="color:#D73A49">!</span><span style="color:#005CC5">empty</span><span style="color:#24292E">($q)) {</span></span> +<span class="line"><span style="color:#24292E"> $qq </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> array_pop</span><span style="color:#24292E">($q);</span></span> +<span class="line"><span style="color:#24292E"> $v[$qq] </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> true</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49"> foreach</span><span style="color:#24292E"> ([$qq</span><span style="color:#D73A49">+</span><span style="color:#005CC5">1</span><span style="color:#24292E">, $qq</span><span style="color:#D73A49">+</span><span style="color:#24292E">$w, $qq</span><span style="color:#D73A49">-</span><span style="color:#005CC5">1</span><span style="color:#24292E">, $qq</span><span style="color:#D73A49">-</span><span style="color:#24292E">$w] </span><span style="color:#D73A49">as</span><span style="color:#24292E"> $qp) {</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> ($cs[$qp] </span><span style="color:#D73A49">!==</span><span style="color:#24292E"> $c1) </span><span style="color:#D73A49">continue</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> (</span><span style="color:#005CC5">isset</span><span style="color:#24292E">($v[$qp])) </span><span style="color:#D73A49">continue</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E"> $q[] </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $qp;</span></span> +<span class="line"><span style="color:#24292E"> $qx </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $qp </span><span style="color:#D73A49">%</span><span style="color:#24292E"> $w;</span></span> +<span class="line"><span style="color:#24292E"> $qy </span><span style="color:#D73A49">=</span><span style="color:#6F42C1"> intdiv</span><span style="color:#24292E">($qp, $w);</span></span> +<span class="line"><span style="color:#24292E"> $x </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $ep </span><span style="color:#D73A49">%</span><span style="color:#24292E"> $w;</span></span> +<span class="line"><span style="color:#24292E"> $y </span><span style="color:#D73A49">=</span><span style="color:#6F42C1"> intdiv</span><span style="color:#24292E">($ep, $w);</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> (</span></span> +<span class="line"><span style="color:#24292E"> ($dp </span><span style="color:#D73A49">===</span><span style="color:#005CC5"> 0</span><span style="color:#D73A49"> &&</span><span style="color:#24292E"> ($x </span><span style="color:#D73A49"><</span><span style="color:#24292E"> $qx </span><span style="color:#D73A49">||</span><span style="color:#24292E"> ($x </span><span style="color:#D73A49">===</span><span style="color:#24292E"> $qx </span><span style="color:#D73A49">&&</span><span style="color:#24292E"> ($y</span><span style="color:#D73A49"><=></span><span style="color:#24292E">$qy) </span><span style="color:#D73A49">===</span><span style="color:#24292E"> $cc)))</span></span> +<span class="line"><span style="color:#D73A49"> ||</span><span style="color:#24292E"> ($dp </span><span style="color:#D73A49">===</span><span style="color:#005CC5"> 1</span><span style="color:#D73A49"> &&</span><span style="color:#24292E"> ($y </span><span style="color:#D73A49"><</span><span style="color:#24292E"> $qy </span><span style="color:#D73A49">||</span><span style="color:#24292E"> ($y </span><span style="color:#D73A49">===</span><span style="color:#24292E"> $qy </span><span style="color:#D73A49">&&</span><span style="color:#24292E"> ($qx</span><span style="color:#D73A49"><=></span><span style="color:#24292E">$x) </span><span style="color:#D73A49">===</span><span style="color:#24292E"> $cc)))</span></span> +<span class="line"><span style="color:#D73A49"> ||</span><span style="color:#24292E"> ($dp </span><span style="color:#D73A49">===</span><span style="color:#005CC5"> 2</span><span style="color:#D73A49"> &&</span><span style="color:#24292E"> ($qx </span><span style="color:#D73A49"><</span><span style="color:#24292E"> $x </span><span style="color:#D73A49">||</span><span style="color:#24292E"> ($qx </span><span style="color:#D73A49">===</span><span style="color:#24292E"> $x </span><span style="color:#D73A49">&&</span><span style="color:#24292E"> ($qy</span><span style="color:#D73A49"><=></span><span style="color:#24292E">$y) </span><span style="color:#D73A49">===</span><span style="color:#24292E"> $cc)))</span></span> +<span class="line"><span style="color:#D73A49"> ||</span><span style="color:#24292E"> ($dp </span><span style="color:#D73A49">===</span><span style="color:#005CC5"> 3</span><span style="color:#D73A49"> &&</span><span style="color:#24292E"> ($qy </span><span style="color:#D73A49"><</span><span style="color:#24292E"> $y </span><span style="color:#D73A49">||</span><span style="color:#24292E"> ($qy </span><span style="color:#D73A49">===</span><span style="color:#24292E"> $y </span><span style="color:#D73A49">&&</span><span style="color:#24292E"> ($x</span><span style="color:#D73A49"><=></span><span style="color:#24292E">$qx) </span><span style="color:#D73A49">===</span><span style="color:#24292E"> $cc)))</span></span> +<span class="line"><span style="color:#24292E"> )</span></span> +<span class="line"><span style="color:#24292E"> $ep </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $qp;</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#24292E"> $np </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $ep </span><span style="color:#D73A49">+</span><span style="color:#24292E"> [</span><span style="color:#005CC5">1</span><span style="color:#24292E">, $w, </span><span style="color:#D73A49">-</span><span style="color:#005CC5">1</span><span style="color:#24292E">, </span><span style="color:#D73A49">-</span><span style="color:#24292E">$w][$dp];</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> ($cs[$np] </span><span style="color:#D73A49">!==</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">) {</span></span> +<span class="line"><span style="color:#24292E"> $b </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> count</span><span style="color:#24292E">(</span><span style="color:#005CC5">array_keys</span><span style="color:#24292E">($v));</span></span> +<span class="line"><span style="color:#24292E"> $pc </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $np;</span></span> +<span class="line"><span style="color:#D73A49"> break</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#24292E"> }</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> ($j </span><span style="color:#D73A49">===</span><span style="color:#005CC5"> 7</span><span style="color:#24292E">) </span><span style="color:#D73A49">break</span><span style="color:#005CC5"> 2</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> ($j </span><span style="color:#D73A49">%</span><span style="color:#005CC5"> 2</span><span style="color:#D73A49"> ===</span><span style="color:#005CC5"> 0</span><span style="color:#24292E">) $cc </span><span style="color:#D73A49">=</span><span style="color:#D73A49"> -</span><span style="color:#24292E">$cc;</span></span> +<span class="line"><span style="color:#D73A49"> if</span><span style="color:#24292E"> ($j </span><span style="color:#D73A49">%</span><span style="color:#005CC5"> 2</span><span style="color:#D73A49"> ===</span><span style="color:#005CC5"> 1</span><span style="color:#24292E">) $dp </span><span style="color:#D73A49">=</span><span style="color:#24292E"> ($dp</span><span style="color:#D73A49">+</span><span style="color:#005CC5">1</span><span style="color:#24292E">) </span><span style="color:#D73A49">%</span><span style="color:#005CC5"> 4</span><span style="color:#24292E">;</span></span> +<span class="line"><span style="color:#6A737D">// The original Piet image is wrong: it outputs 403 error for invalid passwords.</span></span> +<span class="line"><span style="color:#6A737D">// Failure of authentication should be notified by 401, not 403.</span></span> +<span class="line"><span style="color:#6A737D">// I noticed that one month before PHPerKaigi, but I could not read or write (paint)</span></span> +<span class="line"><span style="color:#6A737D">// Piet any longer at that time.</span></span> +<span class="line"><span style="color:#005CC5">fwrite</span><span style="color:#24292E">(</span><span style="color:#005CC5">STDERR</span><span style="color:#24292E">, </span><span style="color:#005CC5">str_replace</span><span style="color:#24292E">(</span><span style="color:#032F62">'403 Forbidden'</span><span style="color:#24292E">, </span><span style="color:#032F62">'401 Unauthorized'</span><span style="color:#24292E">, $o));</span></span></code></pre> + </div> <p> これは一体なんなのか。ずばり、難解プログラミング言語の一つ Piet のインタプリタである。Piet はピエト・モンドリアン (『赤・青・黄のコンポジション』などで知られる抽象画家) の作品にインスピレーションを受けて作られた、画像をソースコードとするプログラミング言語である。インタプリタは画像の各ピクセルの上を進みながら、色等に応じて特定の処理をおこなっていく。ここでは詳しい言語仕様については解説しないので、気になる方は <a href="https://ja.wikipedia.org/wiki/Piet" rel="noreferrer" target="_blank">Wikipedia の記事「Piet」</a> などを参照してほしい。 @@ -401,7 +412,9 @@ $h = $b[24]+2; プログラムの冒頭にあるこの箇所 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$b</span> = <span class="hljs-title function_ invoke__">unpack</span>(<span class="hljs-string">'C*'</span>, <span class="hljs-title function_ invoke__">file_get_contents</span>(<span class="hljs-keyword">__FILE__</span>));</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$b </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> unpack</span><span style="color:#24292E">(</span><span style="color:#032F62">'C*'</span><span style="color:#24292E">, </span><span style="color:#005CC5">file_get_contents</span><span style="color:#24292E">(</span><span style="color:#005CC5">__FILE__</span><span style="color:#24292E">));</span></span></code></pre> + </div> <p> で <code>__FILE__</code> つまりこの画像ファイルを読み込んでいる。先ほど Piet は画像をソースコードにしていると説明した。そう、今回の問題の画像ファイル <code>Q1.png</code> は、PHP 製 Piet インタプリタであると同時に、Piet のソースコード画像でもあるのだ。QR コード中央のカラフルな部分が Piet の命令になっている。 @@ -460,11 +473,13 @@ $h = $b[24]+2; ところで、先ほど掲載した Piet のインタプリタのソースコード末尾には次のような箇所がある。 </p> - <pre class="highlight" language="php"><code class="highlight"><span class="hljs-comment">// The original Piet image is wrong: it outputs 403 error for invalid passwords.</span> -<span class="hljs-comment">// Failure of authentication should be notified by 401, not 403.</span> -<span class="hljs-comment">// I noticed that one month before PHPerKaigi, but I could not read or write (paint)</span> -<span class="hljs-comment">// Piet any longer at that time.</span> -<span class="hljs-title function_ invoke__">fwrite</span>(STDERR, <span class="hljs-title function_ invoke__">str_replace</span>(<span class="hljs-string">'403 Forbidden'</span>, <span class="hljs-string">'401 Unauthorized'</span>, <span class="hljs-variable">$o</span>));</code></pre> + <div class="codeblock" language="php"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D">// The original Piet image is wrong: it outputs 403 error for invalid passwords.</span></span> +<span class="line"><span style="color:#6A737D">// Failure of authentication should be notified by 401, not 403.</span></span> +<span class="line"><span style="color:#6A737D">// I noticed that one month before PHPerKaigi, but I could not read or write (paint)</span></span> +<span class="line"><span style="color:#6A737D">// Piet any longer at that time.</span></span> +<span class="line"><span style="color:#005CC5">fwrite</span><span style="color:#24292E">(</span><span style="color:#005CC5">STDERR</span><span style="color:#24292E">, </span><span style="color:#005CC5">str_replace</span><span style="color:#24292E">(</span><span style="color:#032F62">'403 Forbidden'</span><span style="color:#24292E">, </span><span style="color:#032F62">'401 Unauthorized'</span><span style="color:#24292E">, $o));</span></span></code></pre> + </div> <p> コメントにも書かれているが、この Piet のソースコード画像には誤りがあった。本来 HTTP のステータスコードを真似るのなら、認証の失敗には 401 を返さなければならない。しかし、Piet のソースは 403 を返すように書いてしまっていた。そのことに私が気付いたのは PHPerKaigi 2023 が開催されるひと月前で、その時点で私はこの Piet のソースコードを (ちょうどこの記事でそうなっているのと同じように) 読解できなくなっていた。さらに悪いことに、正しいメッセージ「401 Unauthorized」は元の「403 Forbidden」よりも3文字長い。3文字出力が長くなるということは、それだけ Piet で塗るべきピクセルが増えることを意味する。もはや3文字追加で出力するだけの余白はこの画像に残されていなかった (と思う。腕ききの Piet プログラマならできるかもしれないので挑戦してみてほしい)。 diff --git a/vhosts/blog/public/posts/2025-01-26/yaml-breaking-changes-between-v1-1-and-v1-2/index.html b/vhosts/blog/public/posts/2025-01-26/yaml-breaking-changes-between-v1-1-and-v1-2/index.html index a8f72a21..87efea12 100644 --- a/vhosts/blog/public/posts/2025-01-26/yaml-breaking-changes-between-v1-1-and-v1-2/index.html +++ b/vhosts/blog/public/posts/2025-01-26/yaml-breaking-changes-between-v1-1-and-v1-2/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>【YAML】YAML 1.1 と YAML 1.2 の主な破壊的変更|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -103,14 +102,16 @@ YAML 1.1 では、<code><<</code> という文字列をキーに指定することで、マップをマージすることができた。 </p> - <pre class="highlight" language="yaml"><code class="highlight"><span class="hljs-attr">x:</span> <span class="hljs-meta">&base</span> - <span class="hljs-attr">a:</span> <span class="hljs-number">123</span> -<span class="hljs-comment"># => { "x": { "a": 123 } }</span> - -<span class="hljs-attr">y:</span> - <span class="hljs-string"><<:</span> <span class="hljs-meta">*base</span> - <span class="hljs-attr">b:</span> <span class="hljs-number">456</span> -<span class="hljs-comment"># => { "y": { "a": 123, "b": 456 } }</span></code></pre> + <div class="codeblock" language="yaml"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#22863A">x</span><span style="color:#24292E">: </span><span style="color:#D73A49">&</span><span style="color:#6F42C1">base</span></span> +<span class="line"><span style="color:#22863A"> a</span><span style="color:#24292E">: </span><span style="color:#005CC5">123</span></span> +<span class="line"><span style="color:#6A737D"># => { "x": { "a": 123 } }</span></span> +<span class="line"></span> +<span class="line"><span style="color:#005CC5">y</span><span style="color:#24292E">:</span></span> +<span class="line"><span style="color:#005CC5"> <<</span><span style="color:#24292E">: </span><span style="color:#D73A49">*</span><span style="color:#24292E">base</span></span> +<span class="line"><span style="color:#22863A"> b</span><span style="color:#24292E">: </span><span style="color:#005CC5">456</span></span> +<span class="line"><span style="color:#6A737D"># => { "y": { "a": 123, "b": 456 } }</span></span></code></pre> + </div> <p> 1.2 からはこれができなくなる。 diff --git a/vhosts/blog/public/posts/2025-02-24/phpcon-nagoya-2025-report/index.html b/vhosts/blog/public/posts/2025-02-24/phpcon-nagoya-2025-report/index.html index e929808e..ee924cdc 100644 --- a/vhosts/blog/public/posts/2025-02-24/phpcon-nagoya-2025-report/index.html +++ b/vhosts/blog/public/posts/2025-02-24/phpcon-nagoya-2025-report/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>PHP カンファレンス名古屋 2025 参加レポ|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> diff --git a/vhosts/blog/public/posts/2025-03-27/zip-function-like-command-paste-command/index.html b/vhosts/blog/public/posts/2025-03-27/zip-function-like-command-paste-command/index.html index 33d871d5..c1d25c00 100644 --- a/vhosts/blog/public/posts/2025-03-27/zip-function-like-command-paste-command/index.html +++ b/vhosts/blog/public/posts/2025-03-27/zip-function-like-command-paste-command/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>zip 関数のようなコマンド paste|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> @@ -80,28 +79,34 @@ <code>a.txt</code> </p> - <pre class="highlight"><code>a1 -a2 -a3</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>a1</span></span> +<span class="line"><span>a2</span></span> +<span class="line"><span>a3</span></span></code></pre> + </div> <p> <code>b.txt</code> </p> - <pre class="highlight"><code>b1 -b2 -b3</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>b1</span></span> +<span class="line"><span>b2</span></span> +<span class="line"><span>b3</span></span></code></pre> + </div> <p> <code>ab.txt</code> </p> - <pre class="highlight"><code>a1 -b1 -a2 -b2 -a3 -b3</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>a1</span></span> +<span class="line"><span>b1</span></span> +<span class="line"><span>a2</span></span> +<span class="line"><span>b2</span></span> +<span class="line"><span>a3</span></span> +<span class="line"><span>b3</span></span></code></pre> + </div> <p> ちょうど Python や Haskell などにある <code>zip</code> 関数のような動きをさせたい。 @@ -114,8 +119,10 @@ b3</code></pre> 記事タイトルに書いたように、<code>paste</code> コマンドを使うと実現できる。 </p> - <pre class="highlight"><code>$ paste -d '\ -' a.txt b.txt > ab.txt</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ paste -d '\</span></span> +<span class="line"><span>' a.txt b.txt > ab.txt</span></span></code></pre> + </div> <p> <code>paste</code> コマンドは複数のファイルを引数に取り、それらを1行ずつ消費しながら <code>-d</code> で指定した文字で区切って出力する。<code>-d</code> は区切り文字の指定で、デフォルトだとタブ区切りになる。 @@ -125,22 +132,26 @@ b3</code></pre> ファイル名には <code>-</code> を指定でき、その場合は標準入力から読み込んで出力する。このとき <code>paste - -</code> のように複数回 <code>-</code> を指定すると、指定した回数の行ごとに連結することができる。例えば <code>ab.txt</code> だとこうなる。 </p> - <pre class="highlight"><code>$ paste - - < ab.txt -a1 b1 -a2 b2 -a3 b3</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ paste - - < ab.txt</span></span> +<span class="line"><span>a1 b1</span></span> +<span class="line"><span>a2 b2</span></span> +<span class="line"><span>a3 b3</span></span></code></pre> + </div> <p> これは標準入力を使うとき特有の挙動で、単に同じファイル名を指定してもこうはならない。 </p> - <pre class="highlight"><code>$ paste ab.txt ab.txt -a1 a1 -b1 b1 -a2 a2 -b2 b2 -a3 a3 -b3 b3</code></pre> + <div class="codeblock"> + <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ paste ab.txt ab.txt</span></span> +<span class="line"><span>a1 a1</span></span> +<span class="line"><span>b1 b1</span></span> +<span class="line"><span>a2 a2</span></span> +<span class="line"><span>b2 b2</span></span> +<span class="line"><span>a3 a3</span></span> +<span class="line"><span>b3 b3</span></span></code></pre> + </div> <p> ときどき便利。 diff --git a/vhosts/blog/public/posts/2025-03-28/http-1-1-send-multiple-same-headers/index.html b/vhosts/blog/public/posts/2025-03-28/http-1-1-send-multiple-same-headers/index.html index 5b645245..ef12bbfe 100644 --- a/vhosts/blog/public/posts/2025-03-28/http-1-1-send-multiple-same-headers/index.html +++ b/vhosts/blog/public/posts/2025-03-28/http-1-1-send-multiple-same-headers/index.html @@ -14,8 +14,7 @@ <meta property="og:locale" content="ja_JP"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>【HTTP】HTTP/1.1 で同じヘッダを2回送るとどうなるか|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> - <link rel="stylesheet" href="/hl.css?h=340e65ffd5c17713efc9107c06304f7b"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="single"> <header class="header"> diff --git a/vhosts/blog/public/posts/index.html b/vhosts/blog/public/posts/index.html index b6887c5f..6d11a4bf 100644 --- a/vhosts/blog/public/posts/index.html +++ b/vhosts/blog/public/posts/index.html @@ -14,7 +14,7 @@ <link rel="alternate" type="application/atom+xml" href="https://blog.nsfisis.dev/posts/atom.xml"> <link rel="icon" type="image/svg+xml" href="/favicon.svg"> <title>投稿一覧|REPL: Rest-Eat-Program Loop</title> - <link rel="stylesheet" href="/style.css?h=79020a898c7052f79b32e90376a4497d"> + <link rel="stylesheet" href="/style.css?h=60eb349e583f5bd51518a7eb98598043"> </head> <body class="list"> <header class="header"> |
