From 77d1d07fbc1b8e27125d5d727e1551e9aeaac6c2 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Fri, 17 Mar 2023 01:56:28 +0900 Subject: fix(content): fix XML notations --- content/posts/2021-03-30/phperkaigi-2021.xml | 212 ++++++--------------- .../cpp-you-can-use-keywords-in-attributes.xml | 38 ++-- .../2021-10-02/ruby-then-keyword-and-case-in.xml | 14 +- ...ce-between-autocmd-bufwrite-and-bufwritepre.xml | 40 ++-- .../posts/2022-04-09/phperkaigi-2022-tokens.xml | 47 ++--- ...anner-write-tool-showing-banner-in-terminal.xml | 15 +- content/posts/2022-05-01/phperkaigi-2022.xml | 16 +- .../php-conference-okinawa-code-golf.xml | 24 +-- .../write-fizzbuzz-in-php-2-letters-per-line.xml | 47 ++--- .../2022-10-28/setup-server-for-this-site.xml | 12 +- .../phperkaigi-2023-unused-token-quiz-3.xml | 153 +++++++++------ 11 files changed, 220 insertions(+), 398 deletions(-) (limited to 'content/posts') diff --git a/content/posts/2021-03-30/phperkaigi-2021.xml b/content/posts/2021-03-30/phperkaigi-2021.xml index ea9fb37..3cfbb0b 100644 --- a/content/posts/2021-03-30/phperkaigi-2021.xml +++ b/content/posts/2021-03-30/phperkaigi-2021.xml @@ -44,15 +44,9 @@ Rails のプロジェクトを PHPer のメンバのみでメンテ →他のメンバもわかる PHP にリプレースを検討 - - サーバレス - - - サーバ・インフラの管理が不要 - - - アプリケーションコードの知識だけで保守可能 - + サーバレス + サーバ・インフラの管理が不要 + アプリケーションコードの知識だけで保守可能 ゼロベースで作れる案件が (Railsの件とは別に) あるため、そちらで試験的に導入? @@ -87,18 +81,10 @@ web サービスを作る具体的なイメージがまだ見えない (注: す サーチコンソール 「カバレッジ」の「除外」 多すぎるのは問題→クロールバジェットを浪費している - - クエリの順番を決める - - - 空の値のルールを決めておく - - - リダイレクトすればインデックスはうまくいく - - - リンクが存在する限りクロールはされる - + クエリの順番を決める + 空の値のルールを決めておく + リダイレクトすればインデックスはうまくいく + リンクが存在する限りクロールはされる リニューアル前のURL インデックスは移行される @@ -119,50 +105,32 @@ web サービスを作る具体的なイメージがまだ見えない (注: す 知覚可能 操作可能 理解可能 堅牢 ちゃんとしたHTMLを書く (閉じタグ・入れ子構造など) - - 標準の HTML を適切に使う - - - WAI-ARIA - - - キーボードフレンドリー - - - マシンフレンドリー - - - SEOフレンドリー - + 標準の HTML を適切に使う + WAI-ARIA + キーボードフレンドリー + マシンフレンドリー + SEOフレンドリー button タグ →キーボード h1 タグ →スクリーンリーダー・クローラ a タグ WAI-ARIA HTML では表現できないセマンティクスを追加する - ロール + ロール - - 何をするのか? - - - ユーザーアクションによって変化しない - + 何をするのか? + ユーザーアクションによって変化しない - プロパティ + プロパティ - - 関連づけられたデータ - + 関連づけられたデータ - ステート + ステート - - 現在の状態 - + 現在の状態 @@ -193,37 +161,23 @@ web サービスを作る具体的なイメージがまだ見えない (注: す * ネイティブコードにコンパイルされる言語である必要がある Filesystem in USEr space (FUSE) - - 特定の C の関数を呼ぶことで filesystem が作れる - - - FFI を持つ言語なら FUSE が使える - + 特定の C の関数を呼ぶことで filesystem が作れる + FFI を持つ言語なら FUSE が使える SSHFS / s3fs / Docker Desktop Linux 以外でも使える - - dokany (on Windows) - - - osxfuse - + dokany (on Windows) + osxfuse VFS: システムコールが呼ばれると、ファイルシステムによってコール FUSE: カーネル空間からユーザ空間へ通信 高レベルなラッパで型をつける PHP 以外では Wordpress を FUSE にマウントする実装がある (C, Python など) - - grep できる - - - sed できる - - - 編集できる - + grep できる + sed できる + 編集できる 期待通りの興味深い発表だった。FUSE @@ -239,15 +193,9 @@ web サービスを作る具体的なイメージがまだ見えない (注: す ATDD
- - ユーザーストーリー - - - ユニットテスト - - - CI/CD - + ユーザーストーリー + ユニットテスト + CI/CD ユーザストーリーの受け入れ条件が曖昧になりがち デグレチェックがユニットレベルでは収まらない場合、手動で同じシナリオをテストしている @@ -256,49 +204,31 @@ web サービスを作る具体的なイメージがまだ見えない (注: す 開発チーム支援(コーディング前・コーディング中)/製品批評(コーディング後) - Q1: 技術面 & チーム支援 + Q1: 技術面 & チーム支援 - - TDD - - - ユニットテストなど - + TDD + ユニットテストなど - Q2: ビジネス面 & チーム支援 + Q2: ビジネス面 & チーム支援 - - ATDD - - - ビジネス面の受け入れテストで駆動する - + ATDD + ビジネス面の受け入れテストで駆動する Agile Alliance ユーザストーリーのスキルレベルを高める テストピラミッド + UI Tests + Service Tests + Unit Tests + 異なる粒度のテストを書く - UI Tests - - - Service Tests - - - Unit Tests - - - 異なる粒度のテストを書く - - - 高レベルになるほど、持つべきテストは少なくなる + 高レベルになるほど、持つべきテストは少なくなる - - ピラミッド型になる - + ピラミッド型になる @@ -309,15 +239,9 @@ web サービスを作る具体的なイメージがまだ見えない (注: す 外部品質・内部品質 バーティカルスライスのデリバリー - - cucumber - - - gauge - - - behat - + cucumber + gauge + behat ユビキタス言語 手動テストもspecに書く 自動化は可能だがコスパが悪い 失敗することがわかっているテスト(レッドテスト)はCIから外す @@ -334,15 +258,9 @@ web サービスを作る具体的なイメージがまだ見えない (注: す 型のある世界で生きてきた身として大いに楽しみにしていた発表。
- - PHPStan - - - Phan - - - Psalm - + PHPStan + Phan + Psalm autoload も認識できる bootstrapFiles 編集箇所と利用箇所を CI でチェック ルールレベルを徐々に引き上げていく @@ -408,22 +326,16 @@ text markup * automation PHP8 でエラーレベルの引き上げ - 捕捉すべきもの + 捕捉すべきもの - - recoverable - + recoverable - 捕捉すべきでないもの + 捕捉すべきでないもの - - unrecoverable - - - 開発時に対処できるもの - + unrecoverable + 開発時に対処できるもの @@ -435,25 +347,19 @@ text markup * automation - - 本番で起きてはいけない - + 本番で起きてはいけない - - 本番で起きてはいけない →生じないのだから捕捉もしない - + 本番で起きてはいけない →生じないのだから捕捉もしない - - 起こるかもしれないので本番環境でも考慮する - + 起こるかもしれないので本番環境でも考慮する @@ -524,12 +430,8 @@ private のみ * 依存関係の制御が困難 アーキテクチャテスト クラスの依存関係や実装ルールをコードとして表現し、自動テスト化する - - deptrac - - - phpat - + deptrac + phpat Independent Core Layer Pattern アーキテクチャテストの失敗 * 実装誤り * or アーキテクチャが適切でない * diff --git a/content/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes.xml b/content/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes.xml index f212b7c..4ee22fe 100644 --- a/content/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes.xml +++ b/content/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes.xml @@ -53,15 +53,15 @@ std::cout << "Hello, World!" << std::endl;
- the identifiers that are keywords cannot be used for other purposes; + the identifiers that are keywords cannot be used for other purposes; - The only place they can be used as non-keywords is in an - attribute-token. (e.g. [[private]] is a valid attribute) (since C++11) - - - - + The only place they can be used as non-keywords is in an + attribute-token. (e.g. [[private]] is a valid attribute) (since C++11) + + + +
キーワードでも属性として指定する場合は非キーワードとして使えるらしい。 実際にやってみる。 @@ -91,24 +91,12 @@ std::cout << "Hello, World!" << std::endl; (参考: 同ドラフト)
- - <%{ - - - %>} - - - <:[ - - - :>] - - - %:# - - - %:%:## - + <%{ + %>} + <:[ + :>] + %:# + %:%:## identifier の構文上の要件を満たさないような代替トークン」はこれらが当てはまると思われる。 diff --git a/content/posts/2021-10-02/ruby-then-keyword-and-case-in.xml b/content/posts/2021-10-02/ruby-then-keyword-and-case-in.xml index 4176c67..2901e44 100644 --- a/content/posts/2021-10-02/ruby-then-keyword-and-case-in.xml +++ b/content/posts/2021-10-02/ruby-then-keyword-and-case-in.xml @@ -177,19 +177,13 @@ end まとめ - ifcase の条件の後ろには then;、改行のいずれかが必要 + ifcase の条件の後ろには then;、改行のいずれかが必要 - - 通常は改行しておけばよい - + 通常は改行しておけばよい - - 3.0 で入る予定の case - in でも then 等が必要になる - - - Ruby の構文を正確に知るには (現状) parse.y を直接読めばよい - + 3.0 で入る予定の case - in でも then 等が必要になる + Ruby の構文を正確に知るには (現状) parse.y を直接読めばよい diff --git a/content/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre.xml b/content/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre.xml index ed7f03f..dc3843b 100644 --- a/content/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre.xml +++ b/content/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre.xml @@ -28,15 +28,9 @@ :help に説明があるが、この記事のタイトルにある2つを含めた以下のイベントには、その違いについて説明がない。 - - BufRead/BufReadPost - - - BufWrite/BufWritePre - - - BufAdd/BufCreate - + BufRead/BufReadPost + BufWrite/BufWritePre + BufAdd/BufCreate このうち、BufAdd/BufCreate に関しては、:help BufCreate
@@ -90,39 +84,27 @@ to |EncodingChanged|. 記事タイトルについて言えば、どちらも変わらないので好きな方を使えばよい。あえて言えば、次のようになるだろう。 - BufAdd/BufCreate + BufAdd/BufCreate - - BufCreate は歴史的な理由により (`for historic reasons'') - 存在しているため、新しい方 (`BufAdd) を使う - + BufCreate は歴史的な理由により ("for historic reasons") 存在しているため、新しい方 (BufAdd) を使う - BufRead/BufReadPost + BufRead/BufReadPost - - BufReadPre との対称性のため、あるいは BufWritePost - との対称性のため BufReadPost を使う - + BufReadPre との対称性のため、あるいは BufWritePost との対称性のため BufReadPost を使う - BufWrite/BufWritePre + BufWrite/BufWritePre - - BufWritePost との対称性のため、あるいは BufReadPre - との対称性のため BufWritePre を使う - + BufWritePost との対称性のため、あるいは BufReadPre との対称性のため BufWritePre を使う - FileEncoding/EncodingChanged + FileEncoding/EncodingChanged - - FileEncoding`Obsolete'' - と明言されているので、`EncodingChanged を使う - + FileEncoding`Obsolete'' と明言されているので、`EncodingChanged を使う diff --git a/content/posts/2022-04-09/phperkaigi-2022-tokens.xml b/content/posts/2022-04-09/phperkaigi-2022-tokens.xml index b0c749b..0f5d7be 100644 --- a/content/posts/2022-04-09/phperkaigi-2022-tokens.xml +++ b/content/posts/2022-04-09/phperkaigi-2022-tokens.xml @@ -141,27 +141,13 @@ 実行結果はこちら: https://ideone.com/22VWmb それぞれの絵文字で表された関数が、各命令に対応している。 - - $👉: > - - - $👈: < - - - $👍: + - - - $👎: - - - - $📝: . - - - $🤡: [ - - - $🎪: ] - + $👉: > + $👈: < + $👍: + + $👎: - + $📝: . + $🤡: [ + $🎪: ] , (入力) に対応する関数はない (このプログラムでは使わないので用意していない)。 @@ -286,20 +272,11 @@ assert(10 === +(![].+!![])); ヒント 次に、ソースコードに書いてあるヒントを読んでいく。 - - N それ自体は、42 や 8128 - といったような特別な意味を持たず、ランダムに決められている - - - $token の各要素は、1文字を表す - - - 1文字は 5x5 のセルからなる - - - 出力されるのは、完全な PHPer トークンである - - + N それ自体は、42 や 8128 といったような特別な意味を持たず、ランダムに決められている + $token の各要素は、1文字を表す + 1文字は 5x5 のセルからなる + 出力されるのは、完全な PHPer トークンである + ここで、PHPer トークンは必ず # 記号から始まることを思いだすと、 $token の最初の数字 0x14B499C は、変換の結果 # になるのではないかと予想される (なお、このことは、リポジトリの README diff --git a/content/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal.xml b/content/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal.xml index e05b51f..0acaad5 100644 --- a/content/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal.xml +++ b/content/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal.xml @@ -46,17 +46,10 @@ プログラム 全体の流れは次のようになっている。 - - フォントファイルを読み込む - - - コマンドライン引数を Shift-JIS に変換する (フォントが Shift-JIS - 基準で並んでいるため) - - - 1文字ずつレンダリングしていく - - + フォントファイルを読み込む + コマンドライン引数を Shift-JIS に変換する (フォントが Shift-JIS 基準で並んでいるため) + 1文字ずつレンダリングしていく + big-clock-mode が Go 製なので、今回も Go で書いた。 PNG が標準ライブラリにあったり、Shift-JIS のエンコーディングが準標準ライブラリにあったりしたのは助かった。 diff --git a/content/posts/2022-05-01/phperkaigi-2022.xml b/content/posts/2022-05-01/phperkaigi-2022.xml index 1ef2a29..106b1db 100644 --- a/content/posts/2022-05-01/phperkaigi-2022.xml +++ b/content/posts/2022-05-01/phperkaigi-2022.xml @@ -112,18 +112,10 @@ PHPerKaigi 2023 があるかどうか存じ上げないが、あるとすれば、次の 4つを目標としたい。 - - プロポーザルを出す - - - PHPer チャレンジのトークン問題を 5題作成する - - - 現地に行く - - - PHPer チャレンジで圧勝する - + プロポーザルを出す + PHPer チャレンジのトークン問題を 5題作成する + 現地に行く + PHPer チャレンジで圧勝する
最後になりましたが、PHPerKaigi diff --git a/content/posts/2022-08-27/php-conference-okinawa-code-golf.xml b/content/posts/2022-08-27/php-conference-okinawa-code-golf.xml index 6c9305b..660b4ad 100644 --- a/content/posts/2022-08-27/php-conference-okinawa-code-golf.xml +++ b/content/posts/2022-08-27/php-conference-okinawa-code-golf.xml @@ -31,24 +31,12 @@ 細かいレギュレーションは不明だったので、勝手に定めた。 - - コマンドライン引数の第1引数で受けとる - - - 結果は標準出力に出す - - - コンマの直後にはスペースを1つ置く - - - 末尾コンマは禁止 - - - 数字でないものは入ってこないものとする - - - 負数は入ってこないものとする - + コマンドライン引数の第1引数で受けとる + 結果は標準出力に出す + コンマの直後にはスペースを1つ置く + 末尾コンマは禁止 + 数字でないものは入ってこないものとする + 負数は入ってこないものとする 書いたものがこちら: [<?php $n=$argv[1];foreach([1e4,5e3,2e3,1e3,500,100,50,10,5,1]as$x)for(;$n>=$x;$n-=$x)$r[]=$x;echo implode(', ',$r??[]);?>] diff --git a/content/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line.xml b/content/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line.xml index 5cb5d93..32c88e8 100644 --- a/content/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line.xml +++ b/content/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line.xml @@ -31,35 +31,24 @@ PHP で、次のような制約の下に fizzbuzz を書いた。 - 1行あたりの文字数は2文字までに収めること (ただし <?php タグは除く) + 1行あたりの文字数は2文字までに収めること (ただし <?php タグは除く) - 厳密な定義: <?php タグ以降のソースコードが、2 byte ごとに - ラインフィード (LF) で区切られること + 厳密な定義: <?php タグ以降のソースコードが、2 byte ごとに + ラインフィード (LF) で区切られること + スペースやタブを使用しないこと - スペースやタブを使用しないこと - - - ループのアンロールをしないこと + ループのアンロールをしないこと - - 100 回ループの代わりに 100 回コードをコピペ、というのは禁止 - + 100 回ループの代わりに 100 回コードをコピペ、というのは禁止 - - PHP 7.4〜8.1 で動作すること - - - 実行時に Notice や Warning が出ないこと - - - 標準的なインストール構成の PHP で実現できること - (デフォルトで有効になっていない拡張等を使わないこと) - + PHP 7.4〜8.1 で動作すること + 実行時に Notice や Warning が出ないこと + 標準的なインストール構成の PHP で実現できること (デフォルトで有効になっていない拡張等を使わないこと) 備考: PHP には short_open_tag というオプションがあり、これを有効にするとファイル冒頭の <?php @@ -159,13 +148,13 @@ の範囲内において、名前が 2文字以下の関数は以下のとおりである: - _: gettext のエイリアス + _: gettext のエイリアス - dl: 拡張モジュールをロードする + dl: 拡張モジュールをロードする - pi: 円周率を返す + pi: 円周率を返す (環境によって多少は変わるかも) @@ -173,9 +162,7 @@ で読み込む行為は、レギュレーションで定めた
- - 標準的なインストール構成の PHP で実現できること - (デフォルトで有効になっていない拡張等を使わないこと) + 標準的なインストール構成の PHP で実現できること (デフォルトで有効になっていない拡張等を使わないこと)
@@ -264,9 +251,7 @@ 今回使ったテクニックを説明する前に、余談として、文字列リテラルの短縮法として今回採用しなかったものを紹介する。
- - PHP 7.4〜8.1 で動作すること - + PHP 7.4〜8.1 で動作すること
というルールがない場合、「未定義の定数が評価された場合、その定数の名前が値になる」という @@ -570,9 +555,7 @@ ただし、これでは
- - スペースやタブを使用しないこと - + スペースやタブを使用しないこと
に違反してしまう。スペースが使えないと引数とコマンドを区切れない。これは困った。 diff --git a/content/posts/2022-10-28/setup-server-for-this-site.xml b/content/posts/2022-10-28/setup-server-for-this-site.xml index 6521029..388238b 100644 --- a/content/posts/2022-10-28/setup-server-for-this-site.xml +++ b/content/posts/2022-10-28/setup-server-for-this-site.xml @@ -86,15 +86,9 @@ $ sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak $ sudo vi /etc/ssh/sshd_config - - Port を変更 - - - PermitRootLoginno - - - PasswordAuthenticationno - + Port を変更 + PermitRootLoginno + PasswordAuthenticationno そして設定を反映。 $ sudo systemctl restart sshd diff --git a/content/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3.xml b/content/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3.xml index cd65047..6356597 100644 --- a/content/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3.xml +++ b/content/posts/2023-01-10/phperkaigi-2023-unused-token-quiz-3.xml @@ -16,25 +16,32 @@ -
+
はじめに - 2023 年 3 月 23 日から 25 日にかけて開催予定 (記事執筆時点) の PHPerKaigi 2023 において、 - 昨年と同様に、弊社 デジタルサーカス株式会社 からトークン問題を出題予定である。 - 昨年のトークン問題の記事はこちら: PHPerKaigi 2022 トークン問題の解説 - すでに 2023 年用の問題は作成済みであるが、その制作過程の中でいくつかボツ問ができた。せっかくなので、PHPerKaigi 開催を待つ間に紹介しようと思う。 - 10 月から 2 月まで、毎月 1 記事ずつ公開していく予定 (忘れていなければ → 忘れていたので 12 月公開予定だった記事を今書いている)。 + + 2023 年 3 月 23 日から 25 日にかけて開催予定 (記事執筆時点) の PHPerKaigi 2023 において、 + 昨年と同様に、弊社 デジタルサーカス株式会社 からトークン問題を出題予定である。 + + + 昨年のトークン問題の記事はこちら: PHPerKaigi 2022 トークン問題の解説 + + + すでに 2023 年用の問題は作成済みであるが、その制作過程の中でいくつかボツ問ができた。 + せっかくなので、PHPerKaigi 開催を待つ間に紹介しようと思う。 + + + 10 月から 2 月まで、毎月 1 記事ずつ公開していく予定 (忘れていなければ → 忘れていたので 12 月公開予定だった記事を今書いている)。 + - - その 1 はこちら: PHPerKaigi 2023: ボツになったトークン問題 その 1 - - - その 2 はこちら: PHPerKaigi 2023: ボツになったトークン問題 その 2 - + その 1 はこちら: PHPerKaigi 2023: ボツになったトークン問題 その 1 + その 2 はこちら: PHPerKaigi 2023: ボツになったトークン問題 その 2
-
+
問題 - 注意: これはボツ問なので、得られたトークンを PHPerKaigi で入力してもポイントにはならない。 + + 注意: これはボツ問なので、得られたトークンを PHPerKaigi で入力してもポイントにはならない。 + - "Catchline" と名付けた作品。実行するとトークン #base64_decode('SGVsbG8sIFdvcmxkIQ==') が得られる。 - トークンは PHP の式になっていて、評価すると Hello, World! という文字列になる。PHPer チャレンジのトークンには空白を含められないという制約があるが、こういった形でトークンにすれば回避できる。 + + "Catchline" と名付けた作品。実行するとトークン #base64_decode('SGVsbG8sIFdvcmxkIQ==') が得られる。 + + + トークンは PHP の式になっていて、評価すると Hello, World! という文字列になる。PHPer チャレンジのトークンには空白を含められないという制約があるが、こういった形でトークンにすれば回避できる。 +
解説
概要 - 例外が発生した行数にデータをエンコードし、それを catch で捕まえて表示している。 + + 例外が発生した行数にデータをエンコードし、それを catch で捕まえて表示している。 +
例外オブジェクトの連鎖 - ExceptionError には $previous というプロパティがあり、コンストラクタの第3引数から渡すことができる。主に 2つの用法がある: + + ExceptionError には $previous というプロパティがあり、コンストラクタの第3引数から渡すことができる。主に 2つの用法がある: + - - エラーを処理している途中に起こった別のエラーに、元のエラー情報を含める - - - 内部エラーをラップして作られたエラーに、内部エラーの情報を含める - + エラーを処理している途中に起こった別のエラーに、元のエラー情報を含める + 内部エラーをラップして作られたエラーに、内部エラーの情報を含める - このうち 1つ目のケースは、 finally 節の中でエラーを投げると PHP 処理系が勝手に $previous を設定してくれる。 + + このうち 1つ目のケースは、 finally 節の中でエラーを投げると PHP 処理系が勝手に $previous を設定してくれる。 + - この知識を元に、トークンの出力部を解析してみる。 + + この知識を元に、トークンの出力部を解析してみる。 +
出力部の解析 - 出力部をコメントや改行を追加して再掲する: + + 出力部をコメントや改行を追加して再掲する: + - 出力をおこなう catch 節を見てみると、 Throwable::getPrevious() を呼び出してエラーチェインを辿り、 Throwable::getLine() でエラーが発生した行数を取得している。その行数に 23 なるマジックナンバーを足し、フォーマット指定子 %c で出力している。 - フォーマット指定子 %c は、整数を ASCII コードRAS syndrome と見做して印字する。トークン #base64_decode('SGVsbG8sIFdvcmxkIQ==')b であれば、ASCII コード 98 なので、75 行目で発生したエラー、 + + 出力をおこなう catch 節を見てみると、 Throwable::getPrevious() を呼び出してエラーチェインを辿り、 Throwable::getLine() でエラーが発生した行数を取得している。その行数に 23 なるマジックナンバーを足し、フォーマット指定子 %c で出力している。 + + + フォーマット指定子 %c は、整数を ASCII コードRAS syndrome と見做して印字する。トークン #base64_decode('SGVsbG8sIFdvcmxkIQ==')b であれば、ASCII コード 98 なので、75 行目で発生したエラー、 + 0 / 0, ]]> - によって表現されている。エラーを起こす方法はいろいろと考えられるが、今回はゼロ除算を使った。 - それでは、エラーチェインを作る箇所、関数 f() を見ていく。 + + によって表現されている。エラーを起こす方法はいろいろと考えられるが、今回はゼロ除算を使った。 + + + それでは、エラーチェインを作る箇所、関数 f() を見ていく。 +
データ構成部の解析 - f() の定義を再掲する (エラーオブジェクトの行数を利用しているので、一部分だけ抜き出すと値が変わることに注意): + + f() の定義を再掲する (エラーオブジェクトの行数を利用しているので、一部分だけ抜き出すと値が変わることに注意): + - 前述のように、 finally 節でエラーを投げると PHP 処理系が $previous を設定する。ここでは、エラーを繋げるために f() を再帰呼び出ししている。最初に f() を呼び出している箇所を確認すると、 + + 前述のように、 finally 節でエラーを投げると PHP 処理系が $previous を設定する。ここでは、エラーを繋げるために f() を再帰呼び出ししている。最初に f() を呼び出している箇所を確認すると、 + - f() には 111 / 337 が渡されることがわかる。そこから 1 ずつ減らして再帰呼び出ししていき、0 より小さくなったら f() を引数なしで呼び出す。引数の数が足りないと呼び出しに失敗するので、再帰はここで止まる。 - エラーチェインは、最後に発生したエラーを先頭とした単方向連結リストになっているので、順に + + f() には 111 / 337 が渡されることがわかる。そこから 1 ずつ減らして再帰呼び出ししていき、0 より小さくなったら f() を引数なしで呼び出す。引数の数が足りないと呼び出しに失敗するので、再帰はここで止まる。 + + + エラーチェインは、最後に発生したエラーを先頭とした単方向連結リストになっているので、順に + - - f() の引数が足りないことによる呼び出し失敗 - - - f(0) の呼び出しで発生したゼロ除算 - - - f(1) の呼び出しで発生したゼロ除算 - - - …​ - - - f(37) の呼び出しで発生したゼロ除算 - + f() の引数が足りないことによる呼び出し失敗 + f(0) の呼び出しで発生したゼロ除算 + f(1) の呼び出しで発生したゼロ除算 + + f(37) の呼び出しで発生したゼロ除算 - となっている。出力の際は catch したエラーの getPrevious() から処理を始めるので、1 番目の f() によるエラーは無視され、 f(0) によるエラー、 f(1) によるエラー、 f(2) によるエラー、と出力が進む。 - f()0 を渡したときは 12 行目にある match0 でゼロ除算が起こるので、行数が 12 となったエラーが投げられる。出力部ではこれに 23 を足した数を ASCII コードとして表示しているのだった。 12 + 2335、ASCII コードでは # である。これがトークンの 1文字目にあたる。 + + となっている。出力の際は catch したエラーの getPrevious() から処理を始めるので、1 番目の f() によるエラーは無視され、 f(0) によるエラー、 f(1) によるエラー、 f(2) によるエラー、と出力が進む。 + + + f()0 を渡したときは 12 行目にある match0 でゼロ除算が起こるので、行数が 12 となったエラーが投げられる。出力部ではこれに 23 を足した数を ASCII コードとして表示しているのだった。 12 + 2335、ASCII コードでは # である。これがトークンの 1文字目にあたる。 +
-
+
おわりに - 「行数」というのはトークン文字列をデコードする対象として優れている。 + + 「行数」というのはトークン文字列をデコードする対象として優れている。 + - - トークンの一部や全部が陽に現れない - - - __LINE__ で容易に取得できる - + トークンの一部や全部が陽に現れない + __LINE__ で容易に取得できる - しかし、こういった「変な」プログラムを何度も読んだり書いたりしていると、 __LINE__ を使うのはあまりにありきたりで退屈になる。では、他に行数を取得する手段はないか。こうして Throwable を思いつき、続けてエラーオブジェクトには $previous があることを思い出した。 - 今回エラーを投げるのにゼロ除算を用いたのは、それがエラーを投げる最も短いコードだと考えたからである。もし 3バイト未満で Throwable なオブジェクトを投げる手段をご存じのかたがいらっしゃれば、ぜひご教示いただきたい。……と締める予定だったのだが、0/0 のところを存在しない定数にすれば、簡単に 1バイトを達成できた。ゼロ除算している箇所はちょうど 26 箇所あるので、アルファベットにでもしておけば意味ありげで良かったかもしれない。 + + しかし、こういった「変な」プログラムを何度も読んだり書いたりしていると、 __LINE__ を使うのはあまりにありきたりで退屈になる。では、他に行数を取得する手段はないか。こうして Throwable を思いつき、続けてエラーオブジェクトには $previous があることを思い出した。 + + + 今回エラーを投げるのにゼロ除算を用いたのは、それがエラーを投げる最も短いコードだと考えたからである。もし 3バイト未満で Throwable なオブジェクトを投げる手段をご存じのかたがいらっしゃれば、ぜひご教示いただきたい。……と締める予定だったのだが、0/0 のところを存在しない定数にすれば、簡単に 1バイトを達成できた。ゼロ除算している箇所はちょうど 26 箇所あるので、アルファベットにでもしておけば意味ありげで良かったかもしれない。 +
-- cgit v1.2.3-70-g09d2