蝉は、やがて死ぬる午後に気づいた。ああ、私たち、もっと仕合せになってよかったのだ。:2010年05月分

2010/05/01(Sat)

連休

ちょっくら 大阪へ行ってきます。

2010/05/09(Sun)

今日

isakiさんとこ、GNU grepはmultibyte対応しとりますので LANG=ja_JP.UTF-8 grep なんちゃらをどぞ。

連休中はNetBSDのことはすっかり忘れてたらしいぞ(ひらきn

[NetBSD] 今 hpcarm がナウい

今時 アドエス買いました、なんというドM!

最近はもうどこもNotePCとかPDAの持込はセキュリティ(笑)で持ち込み禁止なので
モバイラからすっかり足を洗っていたのと、自宅に高速回線無くて Willcom AX530IN の
新つなぎ放題 8x 頼りだった貧弱なインターネッツ環境が最近改善されたので
もう使わないなー、これどうすんべー解約するかと思ってたのですが
ebijunさんの NetBSD/hpcarm 起動画面見た瞬間にポチってしまったという。

なのですが 今 Advanced [es] (WS011SH) 以降の機種 {020, 027} って、ストアで買えないのよね。
民事再生のゴタゴタで倉庫から在庫引き上げられたんだかなんだか知らんけど。

そんなことつゆつゆ知らない私は イヤッッホォォォオオォオウ!で機種名すら確かめず
ただ黒い端末でイーエスとかいうやつ!とポチってしまったので
まんまと無印 [es] (WS007SH) 買ってしまいました、しにたい。

ま W-VALUE SELECT の割引額充当で買ったので、いまんところ負担 0 だからいいんだけど
これ本体代金まじめに一括 40k とか払ってたら一週間は寝込んでたレベル。

でもですね機種変するなら W-OAM type G 対応の W-SIM 黒耳(RX430AL)だけ買って
(WS007SH には type G 非対応の青耳が付属)本体は白ロム探すのが一番いいのかな
と思ったんだけど、実は W-SIM 単体で買うと「新つなぎ放題」に「話し放題」が
付けられないのですな、なんともややこしや料金プラン。

今時 Willcom 端末同士で電話するなんてありえなーいキャハハとかいっちゃだめ!

そんな料金プランなので、いま無印 [es] 以外に買える機種はWS004SHだけだし
こっちは キューキュッパで投売りされてるから、W-VALUE SELECTの分割で
月\800余分に払ったほうが損だったわけでして、結果オーライだなこりゃ。
あ、当然こっちの機種も衝動買いましたが何か。

であちこち探して当初の目的だったアドエス(WS011SH)も、未使用品1年保証残で
15kというのを見つけたのでポチりました、イヤッッホォォォオオォオウ!

WS007SH は実質 0, WS004SH は 10k 弱, WS011SH は 15k の〆て 25k で
NetBSD で遊べるマシンが手に入ったということでよしとしませう。

中古はもっと安く手に入る( 証言1  証言2)ので、 5k リミッター縛りの人も買い易いお値段ですね(ぉ

これでiPhone族の前でキーボードカタカタ打ってダセェと蔑まれて
全身でドMの喜びを味わうことができますな、んああー!んああー!

2010/05/11(Tue)

SONY NEX-5/7

Eマウントと書いてβマウントと読むといわれる(ぉ SONY NEX-5/7の発表が うわさどおりきましたな。
デザインからして最近のαとCyber-shotのあいのこ(差別用語)ですが、もうちょいなんとかならんのか。
特にマウント部はシルバーだとレンズが実際以上に大きく見えるから無用な炎上が。

NEXのサイズじゃさすがにαのようにボディ内手振れは無理だろうとはなっから諦めてたけども(要らないともいう)
アダプタ経由でのαレンズがSAM/SSMレンズでもAF非対応というのはねぇ、まぁミノ時代のVマウントもだったけど。
これでαを名乗るのはアレですな、最近エントリクラスのも全部SAM化されてたので期待してた向きも多いはず。
まうちのSAL50/14, SAL2875SAM, SAL70300Gやミノ時代のレンズは大人しくフィルムカメラで使いますわ
(そいやα200全然使ってない)。

モックではなかったチルト可能な液晶はポイント高い、液晶はDSC-TX7と同じみたいね。
こないだ店頭でみたときEVF大嫌いなおいらでもかなり印象良かったので期待。

あとは暗所性能かな、コントラストAFだけってのはせっかくの裏面照射型CMOSの高感度を役立たずにしてしまうのは
動画フォーカスまよいマイマイDSC-WX1で体験済みなんだけど(HX5VとTX7は改善したんですかねー)
この機種はそもそも裏面照射じゃないし、αは高感度ダメダメとよく叩かれる点なんで気になる。
まぁ男は黙って三脚とMFでも全然かまわないんですが、夜の車載動画@首都高とか趣味の人が
買ってレビューしてくれるまで待ちですかね。

Eマウントの本命は こっち、動画ですやね。ソニパナのAVCHD市場でのガチの戦いが始まったつか。
ビデオとカメラがひとつの市場になってくるとキャノニコは尻に火がつくんじゃないかなーという淡い期待。
キャノニコさん是非Eマウント参入どうっすか(はやくしろー間に合わなくなっても知らんぞーAA略)

iマウントと名付けると勝てるかもしれない(ぉ

3D対応はかなりどうでもいい、3Dテレビ売り場で感じたエキスポ'85 からの進歩のなさ感は何。
まぁアバターもコスモ星丸も観てないからぼくよくわかりません ><
でもWX1のスイングパノラマとムービートレーサーは結構おもしろかったので、実際みたら印象変わるかも。

しかしα200/300番台はどうなるんすかね、500番台ですら喰われてしまいそうな気がするんですが。
いつか宝くじ当たった時買う用として900番台だけは是非残していただきたいところなんですが。

しかし16mmのビューファインダー安いよなー、21mmもこんくらいの値段で出してくれると
Rokkor-QH 21mm/F4をオクで落としたらファインダー欠品で涙目なおいらの救いの神なんですが。

2010/05/13(Thu)

[NetBSD] W-ZERO3

先日 WS004SH の投売りを紹介した後、30 台以上捌けてるんですが
まさか全部 NetBSD な人じゃないよね(汗
ちなみに白ロムとありまsが W-SIM は付属しとらんかったです。

NetBSD 入れて遊ぶなら全く不要でしょうけど、W-SIM も動かすんじゃいという
えらい人は別途入手してくだしあ。中古なら1000円くらいか、あるいは
新つなぎ放題 + W-VALUE SELECT で WS007SH もゲット(ぉ

通話はオマケという感じなので2台持ちして PDA と割り切れるなら W-OAM type G の
黒耳 W-SIM がいいのかも、オンラインサインアップ通るかは要確認ですが。

もうちょっと 様子見てWS020SHとかWS027SHの販売が再開するのを待つとか、ムリカナ。

まぁ机の上にケータイが5台(movaとFOMAそれぞれ1台)並んでると、どこのオレオレ詐欺屋ですかという感じ。

[i18n] なぜ X では client 同士で文字化けずに入力やコピペができるのか

雑誌記事クオリティというあたりは華麗にスルーして書いてみるテスト、いちお専門外。

X Windows(釣り針) System とはすなわち無法地帯なので、クライアント同士がどうやって通信するかは

という非常に原始的な仕組みしか決まっとりやせん。

まぁだいたいは ICCCMというものに基づいて通信しようと努力しているらしいですよ?
こいつらは Xlib の Selection APIというものをどう使うかの規約なんですが、この API 自体は

という仕組みですかね。

ぶっちゃけもっと上位のX Toolkitの XtOwnSelection(3) なんか使う方が楽です。
今時だと Xlib/Xt 使うのもめんどくさいので → Motif 使うのもめんどくさいので → 以下略

Selection API ではデータのやりとりをする場合、事前にネゴシエーションが必要です。
行儀悪いアプリも多いのでアレですが、真面目にやると

という感じですかね。

文字列データの場合、使用可能な encoding について Xlib で定義されるのは

だけです、それだけかよ!

しかし Xmu Library の方で定義される拡張 encoding としては以下のものがあります。

Compound Textというのは何かはこのチラシの裏読んでる人にはもはや説明不要でしょう。
0x1b と 可変翼機は漢のロマンです。

更に XFree86 分裂→ X.Org への合流騒動でドサクサに紛れて追加された

というものあります。

変換を行うには

ちう関数を使います、そんで

の存在は一刻も早く忘れ以下略

X は設計が古いので内部コードに COMPOUND_TEXT という統一コードを採用してます。
(なのでCSIではない *2)なので UTF-8 を追加してCSI的にする層を用意してもいいかなとは
思うんですが、まぁこのへんは XFontStruct とかフォント管理の話も絡んでくるんで大変です。

それに UTF-8 だけ特別扱いして Atom を追加するのも変 *3なので(Atom の数も爆発するし)
iconv_open(3) 的なAPIを追加するほうがスマートでしょう。

しかし Xutf8* というAPIを追加するのはナンセンス
じゃ Xtron* とか Xiso2022* も入れるんか!」ちゅーことですよ。

話を戻して、このX*TextListToTextProperty 関数

int XmbTextListToTextProperty(Display *display, char **list, int count,
       XICCEncodingStyle style, XTextProperty *text_prop_return);

int XwcTextListToTextProperty(Display *display, wchar_t **list, int
       count, XICCEncodingStyle style, XTextProperty *text_prop_return);

ですがいずれも第 2, 3 引数に変換前データとデータ長、第 4 引数に変換する encoding を指定します。
指定可能な encoding は直接 Atom を指定するのではなく

typedef enum {
    XStringStyle,               /* STRING */
    XCompoundTextStyle,         /* COMPOUND_TEXT */
    XTextStyle,                 /* text in owner's encoding (current locale)*/
    XStdICCTextStyle,           /* STRING, else COMPOUND_TEXT */
    /* The following is an XFree86 extension, introduced in November 2000 */
    XUTF8StringStyle            /* UTF8_STRING */
} XICCEncodingStyle;

ちゅー enum value を指定します、XTextStyle というのが先の Atom 一覧に含まれなかったもので
現在の locale の encoding への変換を指定するものです。
XA_TEXT に変換するには XTextStyle ではなく XStdICCTextStyle の方を指定します、まぎらわしい。

変換結果はXTextProperty構造体に格納されます。

typedef struct {
    unsigned char *value;               /* same as Property routines */
    Atom encoding;                      /* prop type */
    int format;                         /* prop data format: 8, 16, or 32 */
    unsigned long nitems;               /* number of data items in value */
} XTextProperty;

そしてデータをこの XTextProperty として受け取った側では

を使ってそのアプリケーション自身の locale の encoding へ変換し表示するわけです。

ざっとこんな仕組みで文字が化けないわけです、ややこしいですが結論としては

変換してるから化けない

でした、まる。

次回予告 uxterm とは何か。

*1:Atom は自分で作っていいのですが、すでに定義済のもの(XA_ プレフィックスではじまるマクロが)もあります。
Xatom.h とか Xmu/Atoms.h を参照のこと

*2:まぁISO/IEC 2022は言語を切り替える仕組みで文字コードじゃないという考え方もできますが :D
*3:ならば COMPOUND_TEXT を特別扱いするのも変じゃないかということになりますが、それはその通りで「変」です。
これは歴史的なものなのでしょうがない。むしろなぜUTF-8で同じ間違いをまた犯そうとするのかの方が問題ですやね。

2010/05/15(Sat)

今日

こいつ・・・動くぞ!

2010/05/26(Wed)

[C++][C][NetBSD] stdint.h/cstdint INT{8,16}_C マクロ

id:RiSKさんとこより。

NetBSDの場合なんかでも INT8_C なんかの定義が sys/arch/i386/include/int_const.h では

/* 7.18.4.1 Macros for minimum-width integer constants */

#define INT8_C(c)       c
#define INT16_C(c)      c
#define INT32_C(c)      c
#define INT64_C(c)      c ## LL

#define UINT8_C(c)      c ## U
#define UINT16_C(c)     c ## U
#define UINT32_C(c)     c ## U
#define UINT64_C(c)     c ## ULL

と定義されてるので、オーバーロード失敗しますやね。

ただしこれ ISO/IEC9899:1999(JIS X3010:2003) を読むと 7.18.4 に

7.18.4 整数定数のマクロ 7.18.4 の各箇条での関数形式マクロは, <stdint.h>で定義された型に対
応する整数型をもつオブジェクトの初期化に使用することができる, 整数定数に展開する。(中略)
この式は, 対応する型の式を整数拡張に従って型変換した式と同じ型をもつ。(以下略)

とありますので, この各箇条の中に当然 INT8_C も含まれるので int より小さい型は整数拡張されて
int と同じ大きさになるので、呼び出す側が明示的にキャストしろということだと思うんですよね。

C++の方の仕様は確認する気力がありませんので、CとC++で矛盾する記述があったら教えて plz

ちなみに glibc2 なんかだと

#define INT8_C(value) ((int8_t) value)
#define UINT8_C(value) ((uint8_t) __CONCAT(value, U))
#define INT16_C(value) value
#define UINT16_C(value) __CONCAT(value, U) 

と強制的にキャストしてるみたいですな。
(追記) 大嘘、glibc2はキャストしてませんでした
I'm feeling Lucky な manpage が大変不正確だった模様。

まぁC++でstdint使う場合、事前定義 __STDC_CONSTANT_MACROS が必要なので
処理を変えちゃうのも手なんですが、さすがに sizeof が異なるというのは
CとC++の互換性問題があるよな...

以下余談、そもそも NetBSDの UINT{8,16}_C の実装って変だよね。
整数拡張ルールではどっちもsigned int に収まるので"U" suffix いらないんじゃないですかね。

[C99] 続 stdint.h

ついでに C99 の stdint.h についての若干の解説を追加。

そもそもCというのはハードウェアに密接に関係してる上に歴史も長いので
過去存在したアーキテクチャについての理解がないと、ナンデコンナシヨウガー
と言いたくなる事はうけあいな言語なわけでして。

そもそも uintN_t ってのは実は移植性がありません。
この型は厳密な bit width を提供しなければならず、そのアーキテクチャが用意する
レジスタとかセグメントのサイズと同じである必要がありまして、無理ならサポートしないもアリです。

7.18.1.1 幅指定整数型 型定義名intN_tは, (中略)
これらの型は, 省略可能とする。しかし, 処理系が8, 16, 32又は64ビットの幅をもつ整数型を提供す
る場合, 対応する型定義名を定義しなければならない。

ほらね。

んでこいつに対応する INTn_MAX 定数も同様に厳密性が要求されます。

7.18.2.1 幅指定整数型の限界値
― 幅指定符号付き整数型の最小値	厳密に-(2N-1)

例えば DEC PDP-10 ですが、このマシンは 36bit ワードのマシンで
char = 9bit, short = 18bit, int = 36bit という今時のマシンとは異なる実装です。
ですのでこのマシン上で動作する OS に intN_t/uintN_t を提供する義務はありません。
ちなみに NetBSD/pdp10 では __attribute__((size(N))) を使うことで無理矢理に提供してました。

一方 int_leastN_t に関しては C99 に準拠する限り必ず提供しなければなりません。

7.18.1.2 最少幅指定整数型 型定義名 int_leastN_t は, (中略)
 次の型を必すとする。
	int_least8_t		uint_least8_t
(以下略)

ですので PDP-10では

typedef	signed char	int_least8_t;
typedef short		int_least16_t;

となるわけでして、int_least8_t は 9bit, int_least16_t なら 18bit までの値を
よゆーで持つことができます、よって

	int_least8_t x = 0x100;

とかしてもコンパイラによる overflow 警告とかは出ない可能性があることに注意。

んでこいつに対応する INT_LEASTn_MAX 定数だと「厳密に」の言葉がありません。

7.18.2.2 最少幅指定整数型の限界値
― 最少幅指定符号付き整数型の最小値	-(2N-1)

つまり INT_LEAST8_MIN == INT8_MIN だろうと、INT_LEAST8_MIN < INT8_MIN だろうと
どっちでも許容されるように読めますな、つかそもそも

7.18.2 幅を指定する整数型の限界値 (中略)
値を厳密に規定する場合を除き, (中略) その値以上の大きさ(絶対値)を持たなければならない。

と書いてあるので、どっちでもいいんじゃないかなと。

んで int_fastN_t こいつは更にアレな存在で H8/300 なんかの整数拡張をまじめにやると
性能が劣化するアーキテクチャの為に用意された型であって
まぁこの型を使って計算すれば主導で最適化されるとゆうこと。

ですので H8/300 なんかでは

/* Signed.  */
typedef signed char		int_fast8_t;
#if __WORDSIZE == 64
typedef long int		int_fast16_t;
typedef long int		int_fast32_t;
typedef long int		int_fast64_t;
#else
...

となるべく long int で typedef する実装になっっとりやす。
今が旬のW-ZERO3でも動く!NetBSD/hpcarm(宣伝モード) なんかの ARM アーキテクチャなんかも

/* 7.18.1.3 Fastest minimum-width integer types */
typedef int                        int_fast8_t;
typedef unsigned int              uint_fast8_t;
typedef int                       int_fast16_t;
typedef unsigned int             uint_fast16_t;
typedef int                       int_fast32_t;
typedef unsigned int             uint_fast32_t;

こんなかんじ。

んでこっちの INT_FASTn_MAX 定数にも「厳密に」の言葉がありません。

7.18.2.3 最速最少幅指定整数型の限界値
― 最速最少幅指定符号付き整数型の最小値	-(2N-1)

つまり INT_FAST8_MIN == INT8_MIN だろうと、INT_FAST8_MIN < INT8_MIN だろうと
どっちでも許容されるのは同じちゅーことです。]

(追記)
どっちにも読めるので、白黒はっきりさせるなら WG14にDefect Report投げるかっすねー。

2010/05/27(Thu)

[NetBSD] gdb-7.1

tech-misc@ で gdb-7.1 での wchar_t の扱いについて議論してる件について
ちょっと準備体操をまずはチラシの裏で(今からかよ)

まず gdb の chatset.c がアレな部分をあげつらってみる。

104 iconv_t
105 iconv_open (const char *to, const char *from)
106 {
107   /* We allow conversions from UTF-32BE, wchar_t, and the host charset.
108      We allow conversions to wchar_t and the host charset.  */
109   if (strcmp (from, "UTF-32BE") && strcmp (from, "wchar_t")
110       && strcmp (from, GDB_DEFAULT_HOST_CHARSET))
111     return -1;
112   if (strcmp (to, "wchar_t") && strcmp (to, GDB_DEFAULT_HOST_CHARSET))
113     return -1;
114
115   /* Return 1 if we are converting from UTF-32BE, 0 otherwise.  This is
116      used as a flag in calls to iconv.  */
117   return !strcmp (from, "UTF-32BE");
118 }

これはシステムに iconv がなかりし場合の fallback 用なので、限られた encoding だけサポートするのは構わん。
しかし mbsrtowcs(3)を使わずに、iconv(3)だけ使って wchar_t に変換しようなんて論外ですわ。
よーしパパ strtoull(3) を使わずに iconv_open("unsigned long long int", "decimal") で変換しちゃうぞーと同レベル。

んでお次。

193 #ifndef GDB_DEFAULT_TARGET_CHARSET
194 #define GDB_DEFAULT_TARGET_CHARSET "ISO-8859-1"
195 #endif
196
197 #ifndef GDB_DEFAULT_TARGET_WIDE_CHARSET
198 #define GDB_DEFAULT_TARGET_WIDE_CHARSET "UTF-32"
199 #endif

はいダメ、debugee (普通 target と呼ぶか)の default charset は ISO-8859-1 じゃないし。
ましてや wchar_t は UTF-32 じゃぁありません。
一応これをベタでiconv_open(3)に渡すのではなく

225 static const char *target_wide_charset_name = GDB_DEFAULT_TARGET_WIDE_CHARSET;

wchar_t の内部エンコーディングが変更可能であるような作りにはなってますが
そもそもwchar_tは実装依存なので、iconv(3)のような公開エンコーディング同士を変換する関数で
扱うこと自体がクルットルわけでして。

まぁマクロ名が悪いだけで実は正しい処理をしているという可能性もありますので
もうちょっと我慢して読み進めてみましょう。

515 /* An iterator that returns host wchar_t's from a target string.  */
516 struct wchar_iterator
517 {
...
529   /* The output buffer and its size.  */
530   gdb_wchar_t *out;
531   size_t out_size;
532 };
...
574 int
575 wchar_iterate (struct wchar_iterator *iter,
576                enum wchar_iterate_result *out_result,
577                gdb_wchar_t **out_chars,
578                const gdb_byte **ptr,
579                size_t *len)
580 {
...
591       char *outptr = (char *) &iter->out[0];
...
597
598       size_t r = iconv (iter->desc,
599                         (ICONV_CONST char **) &iter->input, &iter->bytes,
600                         &outptr, &out_avail);
...

ご覧のように iconv の変換結果 (UTF-32) を gdb_wchar_t ちゅう型につっこんどります。
思わず罵りの4文字言葉を吐きそうになりますが、gdb_wchar_t という名前のせいで誤解してる可能性も。
念には念を入れてねるねるねるね、gdb_wchar.h の中身もチェックしましょう。

55 typedef wchar_t gdb_wchar_t;
56 typedef wint_t gdb_wint_t;
57
58 #define gdb_wcslen wcslen
59 #define gdb_iswprint iswprint
60 #define gdb_iswdigit iswdigit
61 #define gdb_btowc btowc
62 #define gdb_WEOF WEOF
63
64 #define LCST(X) L ## X


アッー!
ク、完全にアウト。
wchar_tに無理矢理UTF-32を突っ込んで尚且つワイド文字系関数にそのまま渡してるので
wchar_t != UCS4 な Solaris や *BSD のような「由緒正しい」実装ではまともに動きません。
ちゅーことなので tech-misc@ で提案されてる GNU libiconv を使えという案は却下。

じゃ NetBSD なんかでも正しく動くように gdb を直させましょうという話になるんですがこれが難しい。
__STDC_ISO_10646__ であれば wchar_t は常に UCS4 であると決め打ちでかかっていいんですが
大多数の CSI モデルを採用する libc 実装においては wchar_t の 内部表現を知る方法がありません。

まぁ single-locale modelであれば、現在実行中の wchar_t は現在の locale と紐付いていますから
これを debugee/target から debugger/host に伝達することで(その為に何らかのバックドアが必要にはなるけれども *1)

wchar_t *pws = mal;
len = mbstowcs(NULL, "あいうえお", sizeof("あいうえお"));
pws = malloc(len * sizeof(wchar_t));
mbstowcs(pws, "あいうえお", sizeof("あいうえお"));

なんてコードを実行した結果を

(gdb) p pws
L"あいうえお"

と gdb の print コマンドで表示することは可能ではあるでしょう。

しかしすでに時代は POSIX.2008 が発行され、multi-locale model の時代なのです。
wchar_t の内部表現を知る為には、その wchar_t がどの locale_t により変換されたかを
知る必要があるわけでして、これ 99% 不可能ですよねー。

唯一の可能性としては mbrtowc(3) を乗っ取って全部組み合わせを記録していくとか…おおこわいこわい。

そういうと CSI では不可能なんだから __STDC_ISO_10646__ の方が優れていると言い出す奴が
必ず現れるんですがこれもまた疑問。

そもそも legacy encoding から Unicode への変換は非可逆変換です、デバッグするときに
ありのままの値ではなく変換後の値だけを評価して、あなたはバグ調査ができますか?
例えばWindows-31Jにはいくつか重複文字した文字があって、Unicodeに変換するとnarrowされたりするしね。

これがOOな言語なら 国際化文字(列)クラスは、己をを文字列表現に変換する toString()とか to_str なんかを
実装することになるんでしょうが、C のバヤイ wchar_t は自身の encoding 情報すら持ってないからねぇ。

まぁ結論としては、これまで通り数値として表示すりゃいいじゃん。なんですが
結局 __STDC_ISO_10646__ なら可能、こんなことも出来ない CSI はクソ!と声高に叫ばれると
なかなかこれを捻じ伏せるのが大変なのよね、Xutf8* とかの経験則上。

まぁその場合こっちでも wchar_t の内部表現をCSIのメリットを生かしつつも
統一してしまうという手がないわけではない、例えば itojun m17n の

/*
 * wchar_t mappings:
 * ASCII (ESC ( B)              00000000 00000000 00000000 0xxxxxxx
 * iso-8859-1 (ESC , A)         00000000 00000000 00000000 1xxxxxxx
 * 94 charset (ESC ( F)         0fffffff 00000000 00000000 0xxxxxxx
 * 94 charset (ESC ( M F)       0fffffff 1mmmmmmm 00000000 0xxxxxxx
 * 96 charset (ESC , F)         0fffffff 00000000 00000000 1xxxxxxx
 * 96 charset (ESC , M F)       0fffffff 1mmmmmmm 00000000 1xxxxxxx
 * 94x94 charset (ESC $ ( F)    0fffffff 00000000 0xxxxxxx 0xxxxxxx
 * 96x96 charset (ESC $ , F)    0fffffff 00000000 0xxxxxxx 1xxxxxxx
 * 94x94 charset (ESC & V ESC $ ( F)
 *                              0fffffff 1vvvvvvv 0xxxxxxx 0xxxxxxx
 * 94x94x94 charset (ESC $ ( F) 0fffffff 0xxxxxxx 0xxxxxxx 0xxxxxxx
 * 96x96x96 charset (ESC $ , F) 0fffffff 0xxxxxxx 0xxxxxxx 1xxxxxxx
 * reserved for UCS4 co-existence (UCS4 is 31bit encoding thanks to mohta bit)
 *                              1xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
 */

を使うとかね。

これから POSIX.2008 の multi-locale 実装と、それを使ったアプリケーションが続々と出てくるでしょうが
ja_JP.eucJP の L'あ' は ja_JP.UTF-8 の L'あ' とは同じではないということを知らずに
クソ^W 正しくない実装を量産する奴らがきっと出てくるだろうし、今のうちから正しい使い方を啓蒙してかないと
きっと C1X でまた __STDC_ISO_10646__ を強制(must)にする動きが出てきてしまうかもね。

*1:setlocale(LC_CTYPE, NULL) では 副作用が無い事を保障できないので何らかのOS依存の手段が必要