Barbarism begins at internet:2021年11月03日分

2021/11/03(Wed)

[I18N] ユーザー定義文字クラス

glibc regex(3)でlocale固有のユーザー定義文字クラスを使うには、現状のコードを書き直して一度マルチバイトからワイド文字に変換してwctype(3) + iswctype(3)を使うしかないんじゃないですかね。 元のコード読んでないからよう知らんけど。

ちなみにF方面で国際化対応したHenry Spencer's regexのコードだと以下の部分にあたるコードなのかなと。

1212	/*
1213	 - p_b_cclass_named - deal with a named character class
1214	 == static void p_b_cclass_named(struct parse *p, cset *cs, const char []);
1215	 */
1216	static void
1217	p_b_cclass_named(struct parse *p, cset *cs, const char clname[]) {
1218	        wctype_t wct;
1219	
1220	        if ((wct = wctype(clname)) == 0) {
1221	                SETERROR(REG_ECTYPE);
1222	                return;
1223	        }
1224	        CHaddtype(p, cs, wct);
1225	}
...
1661	/*
1662	 - CHaddtype - add all characters of a certain type to a character set.
1663	 */
1664	static void
1665	CHaddtype(struct parse *p, cset *cs, wctype_t wct)
1666	{
1667	        wint_t i;
1668	        wctype_t *newtypes;
1669	
1670	        for (i = 0; i < NC; i++)
1671	                if (iswctype(i, wct))
1672	                        CHadd(p, cs, i);
1673	        newtypes = reallocarray(cs->types, cs->ntypes + 1,
1674	            sizeof(*cs->types));
1675	        if (newtypes == NULL) {
1676	                SETERROR(REG_ESPACE);
1677	                return;
1678	        }
1679	        cs->types = newtypes;
1680	        cs->types[cs->ntypes++] = wct;
1681	}

それとjkanji/jhira/jkataが「名前が好ましくない」はちょっと意図が汲み取れないですね、これらの名前がポータブルなのか?という意味と解釈した上で回答すると、これらの日本語locale固有の文字クラスは

してるので問題ないんじゃないでしょうか。そもそも無いなら無いで自分で定義ファイル書いて追加できるってのもPOSIX localeの拡張性だし。

歴史的には、1992年に作られたDraft Japanese National Profile for POSIX Version 2.1ではkanji/katakana/hiraganaという名前を将来のために予約するよーとだけあるのだけど、翌年の Version 2.2になると暫定案と但し書きあるけどjkanji/jhira/jkataなどなどを定義するよとなったのだよね。

そんでこれがそのまま同年の UI-OSF日本語環境実装規約 Version 1.1にも採用されて、これをベースに各商用UNIXベンダが実装したという流れのはず、まぁ完全実装したとこは記憶にないけどjkanji/jhira/jkanaくらいはどの商用UNIXでも使えたはず *1

これらの文書が生まれた経緯については実際に規格策定に携わられ、後にLI18NUX2000/OpenI18NでLinuxの国際化に尽力された 沼田さんのブログでも読んでちょーだい。

どうして文字クラス名の頭にjをつけるよう変更したのかは想像するしかないけど(確実なのは5chのなんでも実況J板は無関係だ)、具体的に実装進めていく上で名前空間的なものがあった方がいいって認識になったのかなと推測。 まーでもそれならどうして[:gaiji:]であって[:jgaiji:]ではないのかという謎が残るんだけど、今の時代の誹謗中傷はびこる悪いインターネットだとgaijiってだけで差別用語扱いでポリティカルコレクトネスで名前が変わってた可能性(ぉ。

あと/usr/share/i18n/locale/ja_JPというlocale定義ファイルはあくまでソースファイルなので、こいつに記述しただけでは使えないのだ。 こいつらをlocaledef(1)コマンドに食わせてLinuxなら/usr/lib/locale/ja_JP/LC_*あるいは/usr/lib/locale/locale-archiveというデータベースファイルを作成する必要がある。 説明するのはめんどくさいので詳しいことはマニュアル読んでちょ。

そんでこれらのlocale固有の文字クラスを使うためのAPIだけど、さっきのFのregex(3)のコードの通りwctype.hをインクルードしwctype(3)とiswctype(3)というワイド文字関数を呼ぶ必要がある。 そもそもシングルバイト文字しか扱えないctype.hのis*関数でこれらの文字クラスなぞ意味を成さないしね。

もはやPOSIX localeでのアプリケーション国際化なんて時代遅れもいいとこなので、これらの機能についての情報はインターネットの海に沈んでいくだけなんだよな。 つーかそもそも解説本が日本DECの人が書いた「 国際化プログラミング I18Nハンドブック」という当時1万円超えの書籍くらいしか無かったしな、今は古書で送料込みで1000円せずに買えてしまうんだ…

んで 前も書いたけど、文字クラスってUnicode絵文字扱えないからもはや時代遅れもいいとこだよね、[:emoji:]とか[:facemark:]とか[:animal:]とか無いので困る困らない。

*1:なおワイがちょっとだけ関わっていたNのPOSIX locale実装(Citrus XPG4DL)ではそもそもユーザー定義文字クラスが未実装なのであんまり偉そうな事は言えない。