cygwin/mingwでUTF-32な文字列リテラルを使う

http://blog.practical-scheme.net/shiro/20100211-string-literal-concatenation で思い出した。
moshは文字列リテラルがUCS-4、いわゆるUTF-32であることを前提にしている箇所がいくつかある(この両者は厳密には違うものだけど、C++ソースコード中に書かれる範囲では定義域に問題は無い)。しかし、Windowsではwide charは16bitなので、32bitの文字列リテラルを記述するためのうまい方法は存在しない。
従来のmoshでは、WindowsCygwinでは実行時に定数を変換するという若干トリッキーな手法によって実現されていた(herumi氏による)。

moshソースコードでは、全てのwide文字列リテラルをUC("hoge")のようにして書くというルールが存在するので、これは大体うまく働く。つまり、wide charが32bitの環境では、UCは単にL""を出力するマクロであり、wide charが16bitの環境では変換済み文字列を得る手続になる。しかし、このコードは8bitで表現できない文字を取り扱えないので、一部のテストがCygwinWindows上で通過しない原因になっていた。
nmoshブランチのmoshは、gccのiconv機能を使って文字列リテラルコンパイル時にUCS-4に変換している。これは、コマンドラインオプションとして-fwide-exec-charset=ucs-4leを与えることで行える。

ただ、MinGWのバイナリ配布はこれをサポートしていないか、サポートしていても正常に動作しないケースが多い。現状では、moshMinGWでビルドするメリットは殆ど無いのでこの辺は諦めている。。(多分殆どの人はCygwinを使うだろう)
しかし、この機能は終端のヌル文字を変換してくれないというごもっともな問題がある。。つまり、個々の文字は32bitなのに、ヌル文字だけは16bitという微妙なコードが出力されてしまう。当然、moshはこの16bitのヌルを正常に取り扱えないので単に-fwide-exec-charsetするだけではうまくいかない。
というわけで、Cでは文字列リテラルを連続して書くと連結されるという性質を使って、ヌル文字を付け足している(上記エントリの2)。

これにより、16bitのヌルが2つ連続し、全体で32bitのヌルを構成する。。
VCはどうしようもない。C++0xにはchar32_tやchar16_tが入り、今回のような目的のために使えるが、VCは今のところそのような文字列リテラルの記述をサポートしていないように思える。