perlio.cの問題点のまとめ

perlio.c(v5.10.0)について,私が感じている問題をまとめてみた*1。明確なバグもいくつか見つけたが,それはきちんと報告することにする。したがってこのリストには載せていない。

なお,以下でたびたび出てくるPerlIOBaseというのはレイヤに共通した機能を提供する抽象レイヤである。

ソースコードの可読性の問題

  • stdio/sfioを使うためのコードが一つのファイルに混在
  • Cのstdioの実装次第(バッファへのアクセス可能性)ではデフォルトレイヤが :stdio になるが,実装の違いを吸収するために :stdio の実装が#ifdefの嵐になっている。
  • 無数の重複コード

Perlレベルからみた不可解な仕様

  • PerlIORaw_open() (:rawでopen()するときの処理)が:unixと同じになる(:rawでopen()した後IOが異様に遅いのはそのため)。binmode($fh)と同じ挙動にするべきではないか。
  • Win32環境でbinmode($fh)してもレイヤは:crlfのままでCRLFフラグが取り除かれるだけだが,その他の環境で:crlfでopen()した後(このときレイヤは:unix:crlf)にbinmode($fh)すると,:crlfが取り除かれる(このときレイヤは:unixとなり,バッファリングしなくなる)

Cレベルからみた不可解な仕様

  • Binmode()についてドキュメント(perliol)に記述なし。Perlでbinmode($fh)するとPerlIORaw_pushed()が呼び出され,PerlIORaw_pushed()は以下のような仕様となっているが,(3)と(4)が重複しているのは無駄なので,固有のbinmode()がなければPerlIOBase_binmode()を呼ぶというのが一貫性という意味で望ましいと思われる:
    1. 固有のbinmode()があるときはそれを呼び出す
    2. PerlIOBase_binmodeを継承していて,PERLIO_K_RAWが定義されている場合はPERLIO_F_UTF8フラグを除去
    3. PerlIOBase_binmodeを継承していて,PERLIO_K_RAWが定義されていない場合は,PerlIO_pop()
    4. レイヤがbinmodeを定義していない場合は,PerlIO_pop()
  • Close()とPopped()の違いが不明瞭。実際,PerlIOBuf_close()とPerlIOBuf_popped()の内容はほとんど重複している
  • PerlIOレイヤの「サブクラス化」の概念が分かりにくいうえ,あるクラスのサブクラスかどうかを識別することも不可能である
  • PERLIO_K_FASTGETSとPERLIO_K_BUFFEREDは使われていない。歴史的には意味があったのかもしれないが,今や不要であるからとりあえずドキュメントからは除いたほうがいいと思われる

機能についての要望

  • 低レベルIOのサポート(truncate(), flock(), stat())
  • PerlIO::viaはメソッド実装チェックをもっとしてほしい

*1:まとめてみたら意外と大量にあって驚いた。