Skip to content

Latest commit

 

History

History
428 lines (277 loc) · 12.3 KB

perlhacktut.pod

File metadata and controls

428 lines (277 loc) · 12.3 KB

NAME

perlhacktut - 簡単な C コードパッチの作成を一通り試す

DESCRIPTION

この文書は簡単なパッチの例を一通り試します。

まだ perlhack を読んでいないなら、先に読んでください! perlsource も読み通した方が良いかも知れません。

これが終わったら、次に perlhacktips を見てみてください。

EXAMPLE OF A SIMPLE PATCH

(簡単なパッチの例)

簡単なパッチの作成を最初から最後まで試してみましょう。

Larry が提案したことは、Upack 中で最初に アクティブなフォーマットである場合(たとえば、pack "U3C8", @stuff)、 結果の文字列は UTF-8 エンコードとして扱われるべきであるということです。

Perl リポジトリの git クローン上で作業しているなら、 あなたの変更のためのブランチを作成した方が良いでしょう。 これにより適切なパッチの作成がを大幅に簡単になります。 この方法に関する詳細については perlgit を参照してください。

Writing the patch

(パッチを書く)

この問題を解決するための準備はどうすればいいでしょう? まず問題のコードを見つけます - pack は実行時に発生するので、 pp ファイルの一つにあるはずです。 pp_packpp.c にあります。 このファイルを変更するので、pp.c~ にコピーします。

[そうですね、このチュートリアルが書かれたときは pp.c に書かれていました。 現在は pp_unpack とともに独自のファイル pp_pack.c に分割されています]

pp_packを見てみましょう: パターンを pat に取り込み、そのパターンをループして、各フォーマット文字を 順番に datum_type に取り込みます。 次に、可能なフォーマット文字ごとに、パターン内の他の引数 (フィールド幅やアスタリスクなど)を取り込み、 次のチャンク入力を指定されたフォーマットに変換し、 出力 SV cat に追加します。

Upat の最初のフォーマットであるかどうかはどうすれば わかるでしょう? さて、pat の先頭へのポインタがあれば、U が見つかったら、 まだ文字列の先頭にいるかどうかをテストできます。 ここで pat が設定されています:

STRLEN fromlen;
char *pat = SvPVx(*++MARK, fromlen);
char *patend = pat + fromlen;
I32 len;
I32 datumtype;
SV *fromstr;

ここには別の文字列ポインタがあります:

STRLEN fromlen;
char *pat = SvPVx(*++MARK, fromlen);
char *patend = pat + fromlen;
 +  char *patcopy;
I32 len;
I32 datumtype;
SV *fromstr;

ループを開始する直前に、patcopypat の開始点に設定します。

items = SP - MARK;
MARK++;
SvPVCLEAR(cat);
 +  patcopy = pat;
while (pat < patend) {

文字列の先頭に U がある場合、出力 SV である catに対して UTF8 フラグをオンにします。

+  if (datumtype == 'U' && pat==patcopy+1)
+      SvUTF8_on(cat);
   if (datumtype == '#') {
       while (pat < patend && *pat != '\n')
           pat++;

文字列の最初の文字は datumtype に飲み込まれたUなので、 これは patcopy+1 でなければならないことを覚えておいてください!

おっと、ひとつ忘れていました: パターンの先頭にスペースがあったら? pack(" U*", @stuff) は、パターンの先頭ではないにもかかわらず、 最初のアクティブな文字として U を持ちます。 この場合、スペースがあるときは、pat とともに patcopy を 進める必要があります:

if (isSPACE(datumtype))
    continue;

これは次のようにする必要があります:

if (isSPACE(datumtype)) {
    patcopy++;
    continue;
}

OK。 これで C の部分は完了です。 次に、このパッチを準備する前に、次の二つのことを行う必要があります: Perlの動作を変更したので、その変更を文書化する必要があります。 また、パッチが動作し、他の場所でバグが発生しないことを確認するために、 さらに回帰テストを提供する必要があります。

Testing the patch

(パッチをテストする)

各演算子の退行テストは t/op/ に存在するため、 t/op/pack.t から t/op/pack.t~ へのコピーを作成します。 これで、テストを最後に追加できます。 まず、U が実際に Unicode 文字列を作成することをテストします。

t/op/pack.t には適切な ok() 関数がありますが、そうでなければ t/test.pl の関数を使うことができます。

require './test.pl';
plan( tests => 159 );

それで次のようにする代わりに:

print 'not ' unless "1.20.300.4000" eq sprintf "%vd",
                                              pack("U*",1,20,300,4000);
print "ok $test\n"; $test++;

より実用的な関数を書くことができます (is() やその他のテスト関数の詳細については Test::More を参照してください)。

is( "1.20.300.4000", sprintf "%vd", pack("U*",1,20,300,4000),
                                      "U* produces Unicode" );

では、私たちが最初の場所でビジネスの権利を得たことを テストしてみましょう:

is( "1.20.300.4000", sprintf "%vd", pack("  U*",1,20,300,4000),
                                    "  with spaces at the beginning" );

最後に、Unot である場合、Unicode 文字列を作成しないことを テストします:

isnt( v1.20.300.4000, sprintf "%vd", pack("C0U*",1,20,300,4000),
                                      "U* not first isn't Unicode" );

一番上にあるテストの数を変更することを忘れないでください; さもないと、自動化されたテスターが混乱します。 これは以下のようになります:

print "1..156\n";

または次のようになります:

plan( tests => 156 );

今度は Perl をコンパイルして、テストスイートで実行します。 新しいテストに合格しました、万歳!

Documenting the patch

(パッチの文書を書く)

最後に、文書です。 事務処理が終わるまで仕事は終わらないので、 今行った変更について説明しましょう。 関連する場所は pod/perlfunc.pod です; ここでもコピーを作成し、pack の説明に次のテキストを挿入します:

=item *

If the pattern begins with a C<U>, the resulting string will be treated
as UTF-8-encoded Unicode. You can force UTF-8 encoding on in a string
with an initial C<U0>, and the bytes that follow will be interpreted as
Unicode characters. If you don't want this to happen, you can begin
your pattern with C<C0> (or anything else) to force Perl not to UTF-8
encode your string, and then follow this with a C<U*> somewhere in your
pattern.

Submit

(投稿)

パッチの投稿方法に関する詳細については perlhack を参照してください。

AUTHOR

This document was originally written by Nathan Torkington, and is maintained by the perl5-porters mailing list.