| 1 | use strict; |
|---|
| 2 | use warnings; |
|---|
| 3 | use utf8; |
|---|
| 4 | use lib 'lib'; |
|---|
| 5 | |
|---|
| 6 | use Plusen; |
|---|
| 7 | |
|---|
| 8 | my $p = Plusen->bootstrap({ |
|---|
| 9 | config => { |
|---|
| 10 | meta => { |
|---|
| 11 | title => "PL_check hacks", |
|---|
| 12 | author => 'Kazuhiro Osawa - ( Yappo )', |
|---|
| 13 | email => 'yappo <at> shibuya <döt> pl', |
|---|
| 14 | }, |
|---|
| 15 | plugins => [ |
|---|
| 16 | { module => 'ScriptLoader::Simple' }, |
|---|
| 17 | # { module => 'Device::MozRepl', }, |
|---|
| 18 | { module => 'Device::Term', }, |
|---|
| 19 | { module => 'Device::Growl', }, |
|---|
| 20 | # { module => 'Device::ControlFromFile', config => { path => '/tmp/devsumi-ctl.txt' } }, |
|---|
| 21 | ], |
|---|
| 22 | }, |
|---|
| 23 | }); |
|---|
| 24 | |
|---|
| 25 | __DATA__ |
|---|
| 26 | |
|---|
| 27 | === |
|---|
| 28 | title: XSとは |
|---|
| 29 | |
|---|
| 30 | === |
|---|
| 31 | title: CライブラリとPerlを繋げる物 |
|---|
| 32 | |
|---|
| 33 | === |
|---|
| 34 | title: では無くて |
|---|
| 35 | |
|---|
| 36 | === |
|---|
| 37 | title: パッチをあてずにPerlのコアをhackする物である |
|---|
| 38 | |
|---|
| 39 | === |
|---|
| 40 | title: 謝罪 |
|---|
| 41 | |
|---|
| 42 | === |
|---|
| 43 | title: XS厨どころかInternal厨でごめんなさい |
|---|
| 44 | |
|---|
| 45 | === |
|---|
| 46 | title: 謝罪おわり |
|---|
| 47 | |
|---|
| 48 | === |
|---|
| 49 | title: 50%くらいtokuhiromとかぶったな |
|---|
| 50 | |
|---|
| 51 | === |
|---|
| 52 | title: PL_checkとはなんぞや |
|---|
| 53 | |
|---|
| 54 | === |
|---|
| 55 | title: what is PL_check? |
|---|
| 56 | list: |
|---|
| 57 | - 関数のフックテーブル |
|---|
| 58 | - なんのフック? |
|---|
| 59 | - 構文チェック的な事担当 |
|---|
| 60 | - BEGINフェーズで実行 |
|---|
| 61 | - 構文チェック的な事担当 |
|---|
| 62 | - BEGINフェーズで実行 |
|---|
| 63 | - 大切な事なので2度言いました |
|---|
| 64 | |
|---|
| 65 | === |
|---|
| 66 | title: 例えばこんなコード書いたら |
|---|
| 67 | code: | |
|---|
| 68 | use strict; |
|---|
| 69 | use warnings; |
|---|
| 70 | my $x; |
|---|
| 71 | delete $x; |
|---|
| 72 | |
|---|
| 73 | === |
|---|
| 74 | title: delete argument is not a HASH or ARRAY element or slice |
|---|
| 75 | |
|---|
| 76 | === |
|---|
| 77 | title: と怒られますよね |
|---|
| 78 | |
|---|
| 79 | === |
|---|
| 80 | title: この怒ってる部分がPL_checkで登録された関数が出してる |
|---|
| 81 | |
|---|
| 82 | === |
|---|
| 83 | title: 実装はop.cのPerl_ck_delete(pTHX_ OP *o)を見てね |
|---|
| 84 | |
|---|
| 85 | === |
|---|
| 86 | title: こんなの |
|---|
| 87 | code: | |
|---|
| 88 | OP * |
|---|
| 89 | Perl_ck_delete(pTHX_ OP *o) |
|---|
| 90 | { |
|---|
| 91 | o = ck_fun(o); |
|---|
| 92 | o->op_private = 0; |
|---|
| 93 | if (o->op_flags & OPf_KIDS) { |
|---|
| 94 | OP * const kid = cUNOPo->op_first; |
|---|
| 95 | switch (kid->op_type) { |
|---|
| 96 | case OP_ASLICE: |
|---|
| 97 | o->op_flags |= OPf_SPECIAL; |
|---|
| 98 | /* FALL THROUGH */ |
|---|
| 99 | |
|---|
| 100 | === |
|---|
| 101 | title: つづき |
|---|
| 102 | code: | |
|---|
| 103 | case OP_HSLICE: |
|---|
| 104 | o->op_private |= OPpSLICE; |
|---|
| 105 | break; |
|---|
| 106 | case OP_AELEM: |
|---|
| 107 | o->op_flags |= OPf_SPECIAL; |
|---|
| 108 | /* FALL THROUGH */ |
|---|
| 109 | case OP_HELEM: |
|---|
| 110 | break; |
|---|
| 111 | |
|---|
| 112 | === |
|---|
| 113 | title: つづき(ここでエラー出す) |
|---|
| 114 | code: | |
|---|
| 115 | default: |
|---|
| 116 | Perl_croak(aTHX_ "%s argument is not a HASH or ARRAY element or slice", |
|---|
| 117 | OP_DESC(o)); |
|---|
| 118 | } |
|---|
| 119 | op_null(kid); |
|---|
| 120 | } |
|---|
| 121 | return o; |
|---|
| 122 | } |
|---|
| 123 | |
|---|
| 124 | === |
|---|
| 125 | title: 前ふり終わり、本題に入る |
|---|
| 126 | |
|---|
| 127 | === |
|---|
| 128 | title: tokuhiromの日記見てれば理解できるはずだよ |
|---|
| 129 | |
|---|
| 130 | === |
|---|
| 131 | title: その前にオペコードの構造体の前提知識式だけ |
|---|
| 132 | |
|---|
| 133 | === |
|---|
| 134 | title: OPの定義 see op.h |
|---|
| 135 | code: | |
|---|
| 136 | struct op {//超抜粋 |
|---|
| 137 | /* 次のオペコード */ |
|---|
| 138 | OP* op_next; |
|---|
| 139 | /* 兄弟オペコード? ちょっとわからない */ |
|---|
| 140 | OP* op_sibling; |
|---|
| 141 | /* 実行フェーズで担当する関数 */ |
|---|
| 142 | OP* (CPERLscope(*op_ppaddr))(pTHX); |
|---|
| 143 | /* バイトコード的なコードの種類 */ |
|---|
| 144 | OPCODE op_type; |
|---|
| 145 | // 省略 |
|---|
| 146 | } |
|---|
| 147 | |
|---|
| 148 | |
|---|
| 149 | === |
|---|
| 150 | title: OPの定義 see perl.h |
|---|
| 151 | code: | |
|---|
| 152 | typedef struct op OP; |
|---|
| 153 | |
|---|
| 154 | === |
|---|
| 155 | title: OP は 基本的に OP *o として使うとマクロで扱い易い |
|---|
| 156 | |
|---|
| 157 | === |
|---|
| 158 | title: 何故かというと see op.h |
|---|
| 159 | code: | |
|---|
| 160 | #define cUNOPo cUNOPx(o) |
|---|
| 161 | みたいな定義があるから |
|---|
| 162 | |
|---|
| 163 | === |
|---|
| 164 | title: PL_checkどこで定義されてる? |
|---|
| 165 | list: |
|---|
| 166 | - opecode.h に乗ってる |
|---|
| 167 | - このヘッダファイルには |
|---|
| 168 | - オペコードに対する関数テーブルもある |
|---|
| 169 | - PL_ppaddr がそれ |
|---|
| 170 | - OP で定義された変数の名前は |
|---|
| 171 | - OP_NAME(OP *o) |
|---|
| 172 | - OP で定義された変数の説明は |
|---|
| 173 | - OP_DESC(OP *o) |
|---|
| 174 | - で見れるよ! |
|---|
| 175 | |
|---|
| 176 | |
|---|
| 177 | === |
|---|
| 178 | title: 実際の関数はどこに書いてある? |
|---|
| 179 | list: |
|---|
| 180 | - わかり易く op.c に書いてある |
|---|
| 181 | - Perl_ck_ で始まるのがそうだよ |
|---|
| 182 | - OP *o を受け取ってチェックとかして |
|---|
| 183 | - 構造体とかいじって、OP *oを返す |
|---|
| 184 | - この時 o->op_next は存在しない(はず) |
|---|
| 185 | - なぜなら |
|---|
| 186 | - BEGINフェーズで準備出来てないから |
|---|
| 187 | |
|---|
| 188 | === |
|---|
| 189 | title: ここ迄の知識さえあればPL_checkを書き換えてautoboxみたいなのが作れる! |
|---|
| 190 | |
|---|
| 191 | === |
|---|
| 192 | title: PL_checkを書き換える事、すなわちPerlのコアに麻薬を打ち込んであり得ない幻覚症状を引き起こす |
|---|
| 193 | |
|---|
| 194 | === |
|---|
| 195 | title: そのためには、どのオペコードがどういう役割を持っているかを熟知してる必要がある |
|---|
| 196 | |
|---|
| 197 | === |
|---|
| 198 | title: 俺は熟知して無い |
|---|
| 199 | |
|---|
| 200 | === |
|---|
| 201 | title: オペコード一覧はperl-users.jpのエキスパートPerlに置いてある |
|---|
| 202 | |
|---|
| 203 | === |
|---|
| 204 | title: http://perl-users.jp/expert_perl/op.html |
|---|
| 205 | |
|---|
| 206 | === |
|---|
| 207 | title: PL_check のついでに ppaddr (PL_ppaddr) について |
|---|
| 208 | |
|---|
| 209 | === |
|---|
| 210 | title: ppaddr概要 |
|---|
| 211 | list: |
|---|
| 212 | - オペコード毎に指定されてる |
|---|
| 213 | - OP で言う所の o->op_ppaddr |
|---|
| 214 | - 実行フェーズでは、これに登録されてる関数を |
|---|
| 215 | - オペコードの実際の処理として処理する |
|---|
| 216 | - 実際は pp.c や pp_*.c に関数定義されてる |
|---|
| 217 | - OP_ENTERSUB なら PP(pp_entersub) {} な感じ |
|---|
| 218 | |
|---|
| 219 | === |
|---|
| 220 | title: ppaddrのhack |
|---|
| 221 | list: |
|---|
| 222 | - OP * ppaddr_hack(pTHX) {} |
|---|
| 223 | - こんな感じで pTHX 受け取って OP *o 返す |
|---|
| 224 | - 返す o は次に実行するオペコード |
|---|
| 225 | - とは言っても、返す o は自分で作んない方がよい |
|---|
| 226 | - 今実行してるオペコードは PL_op で取る |
|---|
| 227 | |
|---|
| 228 | === |
|---|
| 229 | title: ppaddrまとめ |
|---|
| 230 | list: |
|---|
| 231 | - PL_checkはPerlコア全体に影響があるが |
|---|
| 232 | - ppaddrはhackしても影響範囲が |
|---|
| 233 | - 特定のオペコードのみという特性がある |
|---|
| 234 | - 特定のクロージャ関数だけ実行方法を |
|---|
| 235 | - 変えるhackとかが出来る |
|---|
| 236 | |
|---|
| 237 | === |
|---|
| 238 | title: そういうhackをちょっとやってみてる(まだ動かない><) |
|---|
| 239 | |
|---|
| 240 | === |
|---|
| 241 | title: http://svn.coderepos.org/share/dan/perl/Object-with/branches/yappo/ |
|---|
| 242 | |
|---|
| 243 | === |
|---|
| 244 | title: ppaddrの使い方(超略例) |
|---|
| 245 | code: | |
|---|
| 246 | static OP *(*next_bak)(pTHX_ OP *op) = NULL; |
|---|
| 247 | OP * ppaddr_hack(pTHX) { |
|---|
| 248 | PerlIO_printf(PerlIO_stderr(), "わーい\n"); |
|---|
| 249 | return PL_ppaddr[PL_op->op_type](aTHX); |
|---|
| 250 | } |
|---|
| 251 | OP * hack_next(pTHX_ OP *o) { |
|---|
| 252 | o->op_ppaddr = ppaddr_hack; |
|---|
| 253 | return CALL_FPTR(next_bak)(aTHX_ o); |
|---|
| 254 | } |
|---|
| 255 | |
|---|
| 256 | === |
|---|
| 257 | title: ppaddrの使い方(超略例)XS部分 |
|---|
| 258 | code: | |
|---|
| 259 | BOOT: |
|---|
| 260 | next_bak = PL_check[OP_NEXT]; |
|---|
| 261 | PL_check[OP_NEXT] = hack_next; |
|---|
| 262 | |
|---|
| 263 | === |
|---|
| 264 | title: これを使うとPerl の next を実行するたびに「わーい」と表示されてうざくなります |
|---|
| 265 | |
|---|
| 266 | |
|---|
| 267 | === |
|---|
| 268 | title: |
|---|
| 269 | |
|---|
| 270 | === |
|---|
| 271 | title: 実際のコードを見ながら説明する時間があれば? |
|---|
| 272 | |
|---|
| 273 | === |
|---|
| 274 | title: http://svn.coderepos.org/share/dan/perl/PL_check/trunk/ |
|---|
| 275 | |
|---|
| 276 | === |
|---|
| 277 | title: 以上です、ご清聴ありがとうございました |
|---|