デバッグのためのデバッグのためのデバッグ

MinGW版はBufferdFileBinaryInputPort.cpp:179 でASSERT

Consoleに直接アクセスしてるとCygwinの端末やシェルスクリプトから使えない(= gdbが使えない)ので回避ルーチンを書く(要するに元に戻す)
(そもそも自前のターミナルエミュレータを前提に作ってあるskymoshに関してはこの部分のパッチを常に行っている)

しかし、それらが上手く働いているのかを確かめる術がない

アナリストのデザイン

コンソールのcodepageをUTF-8(65001)に設定するのってなんでダメなんだっけ*1
もっとも :

  • Win32コンソールやそれを使うアプリケーションは多言語の扱いが圧倒的に間違っている
    • chcp 65001してUTF-8なアプリケーションを動かして直ぐ動くわけではない(ことが多い)
    • (よってアプリケーション側からもそれを期待するべきでないから、Win32コンソールを使うという判断ではWriteConsoleを使うのが正解。WriteConsoleWはコンソールの文字コード設定に応じてwcharを正常に変換してくれる )
  • Win32コンソールを使うとアトリビュートの設定が比較的面倒
  • Win32コンソールはコピペが面倒
  • Write/ReadConsoleはコンソールにしか使えないのでstdout/in/errがコンソールかどうかを判別するコードが必要

emacs必須とかで一つ。。

異文化

まぁ、要するに諸悪の根源はUNIXとWin32で多言語周りに関するデザインチョイスがかなり違うことだとは思う。
まず、Cの標準でwchar枠を作って、Cの標準ライブラリのうち文字列の処理とかは共通化され、fopenとかはそのままになったという前提を考える。

プログラムは明示的にwcharに対応する必要が生じ、かつ、標準的なwchar対応のopenやstatは準備されなかった(なぜならそれらはシステムコールだから)
今でも多くのアプリケーションはwcharではなくcharを使い、メッセージなどの必要に応じてはgettextなど別の方法論を使っている。

WinNTはそもそもwcharを前提にデザインされているので*2、すべてのAPIはwcharを受け入れるようにデザインされている。
同時にWin9xのようなcharを前提にデザインされたシステムとソースコードを共通化したいという需要も有るわけで、ほぼ全ての必要なAPIと構造体にはwchar版とchar版の両方が用意され、コンパイル時にUNICODEが定義されているかどうかで切り替えられるようになった。
つまりCreateFileとだけソースコードに書かれていても、実際に呼ばれるのはCreateFileA(char版)とかCreateFileW(wchar版)と別々の関数になる*3。実際にはWinNTの内部はUnicodeで処理しているので、〜Aの関数はwrapperであり実際の処理を行うのは〜Wになる(Win9xは逆)。WindowsCEではそもそも〜Aが存在しない(常に/DUNICODEされる)。

選択肢

どう対処するのかは様々な選択肢があるし、これはどれが望ましいとも一概には言えない。

  • 1. Win32を全面的に使い、OS抽象化ライブラリを作る(現在のチョイス)
    • 1a. Win32をFFIで使い、ファイルシステムは抽象化する - 各種パフォーマンスチューニングのためにはこちらが望ましい(非同期I/O等は仕組みが違うからどっちみちロジックを共通化できない)
  • 2. Cライブラリをshift-jisで使う(個人的なおすすめ - VCのランタイムよりもCランタイムを上手く作れる自信が無いなら)
    • 2a. wchar版のCライブラリも混ぜる(printfにおける%lsとか)
  • 3. skymoshのように必要最低限の入出力だけを言語実装に持ち、残りをSchemeに移行する
  • 4. Win32側に揃えて、Cライブラリの方をwrapする
  • 5. GlibとGtkを使う

追記 : そもそも、プログラムのコードページをUTF-8に変えたら、Cライブラリをそのまま使うだけでよくなったりしないだろうか。。
追記 : わざわざ断ってあった

ANSIOEM、またはオペレーティング システムがサポートする他のコード ページ値に関係なく、その他の有効なコード ページ値 (サポートされていない UTF-7 および UTF-8 を除く)

*1:本来は、filenameに対するtranscoderが無いって話だったような。。

*2:因果の逆転だ! - そう考える方が都合が良い

*3:僕がMoshにコードを書くときはUTF-16前提のところでは常に〜Wを使うようにしている。今の所Moshのコード中には両者が混在している。