この章では、Solaris 9 環境に含まれているいくつかの国際化機能について説明します。
EUC は Extended UNIX Code の省略形です。 Solaris 9 オペレーティング環境は、日本の PC-Kanji (Shift_JIS)、台湾の Big5、中華人民共和国の GBK のような非 EUC エンコーディングをサポートしています。 コンピュータ市場の大半では EUC 以外のコードセットサポートが要求されるため、Solaris 9 では EUC と非 EUC コードセットのサポートを可能にする強固なフレームワークを提供します。このサポートを CSI と呼びます。
CSI の目標は、Solaris オペレーティング環境のライブラリやコマンドから、特定のコードセットやエンコーディング方法への依存性を除去することです。CSI アーキテクチャにより、Solaris 環境において UNIX ファイルシステムに安全なエンコーディングをサポートできます。CSI は UTF-8、PC-Kanji、Big5 など、多くの非 EUC コードセットをサポートします。
CSI により、アプリケーションおよびプラットフォームソフトウェア開発者は、UTF-8 など、エンコーディングからコードを独立させたり、ソースコードを変更せずに新しいエンコーディングを採用することができます。このアーキテクチャのアプローチは、JavaTM の国際化とも異なります。Java のアプリケーションは UTF-16 に依存する必要があります。
既存の多くの国際化アプリケーション (たとえば Motif など) は、基礎となるシステムから自動的に CSI のサポートを継承します。これらのアプリケーションは、変更しなくても新しいロケールで動作します。
CSI は本来どのコードセットにも依存しませんが、Solaris 9 環境ではファイルコードのエンコーディング (コードセット) には、次のような前提条件があります。
NULL で終わる複数バイトの文字列をサポートする必要があるため、複数バイト文字の一部に NULL (0x00) を使用することはできない。
UNIX のパス名をサポートする必要があるため、複数バイト文字の一部に ASCII のスラッシュ (0x2f) を使用することはできない。
この項では、Solaris 9 環境で使用できる CSI 対応のコマンドを示します。各コマンドのマニュアルページには、コマンドが CSI 対応かどうかを示す属性部分があります。
特に断りがない限り、これらのコマンドは /usr/bin ディレクトリに格納されています。
libc (/usr/lib/libc.so) のほとんどすべての関数は CSI に対応しています。しかし、libc の以下の関数は EUC 依存の関数であるため、CSI に対応していません。
csetcol()
csetlen()
euccol()
euclen()
eucscol()
getwidth()
csetno()
wcsetno()
Solaris 9 製品の libgen (/usr/ccs/lib/libgen.a) と libcurses (/usr/ccs/lib/libcurses.a) は国際化されていますが、 CSI に対応していません。
ロケールデータベースの形式と構造は公開されていません。そのため、将来のリリースで変更されることがあります。したがって、国際化アプリケーションを作成するときには、このロケールデータベースに直接アクセスしないようにしてください。その代わりに libc の国際化 API を使用してください ( libc の国際化 を参照)。
Solaris 9 環境を使用する場合は、Solaris 9 製品に含まれているロケールデータベースを使用してください。以前のバージョンの Solaris のロケールデータベースを使用しないでください。
プロセスコードの書式 (Solaris 9 製品ではワイド文字コード形式ともいう) は公開されていません。そのため、将来のリリースで変更されることがあります。したがって、国際化アプリケーションを作成するときには、このワイド文字の形式が将来変更される可能性があることに注意してください。その代わりに libc の国際化 API を使用することをお勧めします ( libc の国際化 を参照)。
Unicode ロケールのプロセスコードは UTF-32 で表現されています。UTF-32 の詳細については、Unicode Consortium (http://www.unicode.org/ ) の「Unicode Standard Annex #19: UTF 32」と「Unicode Standard Annex #27: Unicode 3.1」を参照してください。
複数バイト文字とは、中国語や日本語、韓国語などのようにシングルバイトに収容できない文字のことをいいます。複数バイト文字を格納するには、2、3、または 4 バイトが必要です。より詳細な定義については、ISO/IECC 9899:1990 サブクラス 3.13 の項目を参照してください。
ANSI C の Amendment 1 (ISO/IEC 9899:1990) では、Multibyte Support Environment (MSE) と呼ぶ新しい国際化機能が追加されました。Amendment 1 には、状態属性をもつ複数バイトコードセットやワイド文字の処理サポートを強化するための新しい国際化 API が定義されています。
プログラミングモデルでは、これらの複数バイト文字を論理ユニットとして読み込み、ワイド文字として内部的に保持できます。プログラム内において、ワイド文字は論理エン ティティとして独立して取り扱うことができます。また、適切な変換処理を行なったのち、これらワイド文字を論理ユニットとして出力できます。
この手順は、シングルバイト文字を読み込んで加工したのち出力する場合と似ています。このため MSE では、シングルバイト文字の場合と同じプログラミングモデルを用いて複数バイト文字を取り扱うためのプログラムを作成できます。
Solaris 9 では、アプリケーションを libc などのシステムライブラリにリンクする方法として、動的リンクと静的リンクを選択できます。しかし、システムライブラリの国際化機能を必要とするアプリケーションは、動的にリンクしなければなりません。このようなアプリケーションが静的にリンクされている場合は、setlocale 関数を使用してロケールを C または POSIX 以外のものに設定する操作は失敗します。静的にリンクされたアプリケーションは、C および POSIX ロケールでのみ動作します。
デフォルトでは、リンカープログラムはアプリケーションを動的にリンクしようとします。リンカーやコンパイラのコマンド行のオプションとして、-Bstatic や -dn を指定すると、アプリケーションは静的にリンクされる場合があります。既存のアプリケーションが動的にリンクされているかどうかを調べるには、/usr/bin/ldd コマンドを使用します。
% /usr/bin/ldd /sbin/sh
このコマンドは以下のメッセージを表示します。このメッセージは、/sbin/sh コマンドが動的にリンクされたプログラムではないことを示しています。
ldd: /sbin/sh: file is not a dynamic executable or shared object
% /usr/bin/ldd /usr/bin/ls
このコマンドは以下のメッセージを表示します。
libc.so.1 => /usr/lib/libc.so.1 libdl.so.1 => /usr/lib/libdl.so.1
このメッセージは、/usr/bin/ls コマンドは 2 つのライブラリ libc.so と libdl.so.l に動的にリンクされていることを示します。
libw と libintl は libc に移動されました。したがって、libw や libintl はありません。
共有オブジェクトは、既存のアプリケーションの実行の互換性を保証し、アーカイブとともにアプリケーションのビルド (コンパイル) 環境の互換性を提供します。ただし、libw や libintl 付きでアプリケーションをビルドする必要はなくなりました。
フィルタの詳細については、『リンカーとライブラリ』を参照してください。
次のリストは、libw のスタブ (Stub) エントリポイントを示しています。
次のリストは、libintl のスタブエントリポイントを示しています。
文字の分類や文字の変換マクロは、/usr/include/ctype.h で定義されています。Solaris 9 環境は、XPG4 で定義されている文字の分類および変換セマンティクスをサポートする一連の ctype マクロをサポートしています。XPG4 や XPG4.2 アプリケーションから新しいマクロに自動的にアクセスするためには、次の条件のどれかが満たされていなければなりません。
_XPG4_CHAR_CLASS が定義されている
_XOPEN_SOURCE および _XOPEN_VERSION=4 が定義されている
_XOPEN_SOURCE および _XOPEN_SOURCE_EXTENDED=1 が定義されている
_XOPEN_SOURCE、_XOPEN_VERSION、_XOPEN_SOURCE_ECTENDED は、新しい ctype マクロの他に XPG4 関連機能をもたらすので、XPG4 または XPG4.2 以外のアプリケーションは _XPG4_CHAR_CLASS_ を使用しなければなりません。
これに対応する ctype 関数もあります。Solaris 9 環境は XPG4 セマンティクスもサポートします。詳細については、ctype(3C) のマニュアルページを参照してください。
Solaris 9 環境は 2 種類の API を提供します。
複数バイト (ファイルコード)
ワイド文字 (プロセスコード)
ワイド文字コードは、一定の幅をもつ論理エンティティです。したがって、複数バイトを使用する時のように適切な文字境界を管理する必要はありません。
プログラムでファイルを読み取る際には、 fscanf(3S) や fwscanf(3S) などの入力関数を使ってファイルの複数バイトデータを直接ワイド文字のプロセスコードに変換できます。あるいは、データを入力した後で mbtowc(3C) や mbsrtowcs(3C) などの変換関数を使ってデータを変換することもできます。 出力データのワイド文字形式を複数バイト文字形式に変換する場合は、fwprintf(3S) や fprintf(3S) などの出力関数を使って直接変換するか、出力前に wctomb(3C) や wcsrtombs(3C) などの変換関数を使って変換します。
以下の各表に、Solaris 9 製品の国際化 API を示します。
次の表に libc のメッセージング関数 API を示します。
表 2–1 libc のメッセージング関数
ライブラリルーチン |
説明 |
---|---|
catclose() |
メッセージカタログを閉じる |
catgets() |
プログラムメッセージを読み取る |
catopen() |
メッセージカタログを開く |
dgettext() |
指定したドメインのメッセージカタログからメッセージを取得する |
dcgettext() |
指定したドメインとカテゴリのメッセージカタログからメッセージを取得する |
textdomain() |
現在のドメインを設定および照会する |
bindtextdomain() |
メッセージドメインパスをバインドする |
gettext() |
メッセージデータベースからテキスト文字列を取得する |
次の表に libc のコード変換関数 API を示します。
表 2–2 libc のコード変換関数
ライブラリルーチン |
説明 |
---|---|
iconv() |
コードを変換する |
iconv_close() |
変換記述子の割り当てを解除する |
iconv_open() |
変換記述子を割り当てる |
次の表に libc の正規表現 API を示します。
表 2–3 libc の正規表現関数
ライブラリルーチン |
説明 |
---|---|
regcomp() |
正規表現をコンパイルする |
regexec() |
正規表現の照合を実行する |
regerror() |
エラーコードとエラーメッセージのマッピングを行う |
regfree() |
regcomp() により割り当てられたメモリーを解放する |
fnmatch() |
ファイル名またはパス名を照合する |
次の表に libc のワイド文字関数 API を示します。
表 2–4 libc のワイド文字クラス
ライブラリルーチン |
説明 |
---|---|
wctype() |
文字クラスを定義する |
wctrans() |
文字のマッピングを定義する |
次の表に libc のロケールの変更および照会を行う API を示します。
表 2–5 libc の変更および照会ロケール
ライブラリルーチン |
説明 |
---|---|
setlocale() |
プログラムのロケールを変更および照会を行う |
次の表に libc のロケールデータを照会する API を示します。
表 2–6 libc の照会ロケールデータ
ライブラリルーチン |
説明 |
---|---|
nl_langinfo() |
現在のロケールの言語および文化情報を取得する |
localeconv() |
現在のロケールの通貨および数値形式の情報を取得する |
次の表に libc の文字分類関数 API を示します。
表 2–7 libc の文字分類および翻字関数
ライブラリルーチン |
説明 |
---|---|
isalpha() |
文字はアルファベットか |
isupper() |
文字は大文字か |
islower() |
文字は小文字か |
isdigit() |
文字は数か |
isxdigit() |
文字は 16 進数か |
isalnum() |
文字は英数字か |
isspace() |
文字は空白か |
ispunct() |
文字は句読点か |
isprint() |
文字は印刷可能か |
iscntrl() |
文字は制御文字か |
isascii() |
文字は ASCII 文字か |
isgraph() |
文字は表示可能な文字か |
isphonogram() |
ワイド文字は表音文字か |
isideogram() |
ワイド文字は表意文字か |
isenglish() |
ワイド文字は補助コードセットの英語のアルファベットか |
isnumber() |
ワイド文字は補助コードセットの数か |
isspecial() |
ワイド文字は補助コードセットの文字か |
iswalpha() |
ワイド文字はアルファベットか |
iswupper() |
ワイド文字は大文字か |
iswlower() |
ワイド文字は小文字か |
iswdigit() |
ワイド文字は数か |
iswxdigit() |
ワイド文字は 16 進数か |
iswalnum() |
ワイド文字は英数字か |
iswspace() |
ワイド文字は空白か |
iswpunct() |
ワイド文字は句読点か |
iswprint() |
ワイド文字は印刷可能な文字か |
iswgraph() |
ワイド文字は表示可能な文字か |
iswcntrl() |
ワイド文字は制御文字か |
iswascii() |
ワイド文字は ASCII 文字か |
toupper() |
小文字を大文字に変換する |
tolower() |
大文字を小文字に変換する |
towupper() |
ワイド文字の小文字を大文字に変換する |
towlower() |
ワイド文字の大文字を小文字に変換する |
towctrans() |
ワイド文字のマッピング |
次の表に libc の文字照合関数 API を示します。
表 2–8 libc の文字照合関数
ライブラリルーチン |
説明 |
---|---|
strcoll() |
文字列を照合する |
strxfrm() |
文字列を照合用に変換する |
wcscoll() |
ワイド文字の文字列を照合する |
wcsxfrm() |
ワイド文字の文字列を照合用に変換する |
次の表に libc の通貨処理関数 API を示します。
表 2–9 libc の通貨処理関数
ライブラリルーチン |
説明 |
---|---|
localeconv() |
現在のロケールの通貨形式情報を取得する |
strfmon() |
通貨の値を文字列表現に変換する |
次の表に libc の日付と時間の処理関数を示します。
表 2–10 libc の日付と時間の処理関数
ライブラリルーチン |
説明 |
---|---|
getdate() |
ユーザー形式の日付と時間を変換する |
strftime() |
日付と時間を文字列表現に変換する。%u の変換機能は、X/Open CAE 仕様、System Interfaces and Headers, Issue 4, Version 2 に準拠しています。この機能は、10 進法の 1 から 7 で週日を表しており、現在では 1 が月曜日を表します。 |
strptime() |
日付と時間の変換 |
次の表に libc の複数バイト処理関数 API を示します。
表 2–11 libc の複数バイト処理関数
ライブラリルーチン |
説明 |
---|---|
btowc() |
シングルバイトからワイド文字に変換する |
mbrlen() |
1 つの文字に含まれるバイト数を取得する (再起動可能) |
mbsinit() |
変換オブジェクトの状態を決定する |
mbrtowc() |
1 つの文字を 1 つのワイド文字に変換する (再起動可能) |
mbsrtowcs() |
文字列をワイド文字の文字列に変換する (再起動可能) |
mblen() |
文字のバイト数を取得する |
mbtowc() |
1 つの文字を 1 つのワイド文字に変換する |
mbstowcs() |
文字列をワイド文字の文字列に変換する |
次の表に libc のワイド文字および文字列処理関数を示します。
表 2–12 libc のワイド文字および文字列処理
ライブラリルーチン |
説明 |
---|---|
wcsncat() |
ワイド文字の文字列を長さ n に連結する |
wsdup() |
ワイド文字の文字列を重複させる |
wcscmp() |
ワイド文字の文字列を比較する |
wcsncmp() |
ワイド文字の文字列を長さ n 分比較する |
wcscpy() |
ワイド文字の文字列をコピーする |
wcsncpy() |
ワイド文字の文字列を長さ n 分コピーする |
wcschr() |
ワイド文字の文字列内の文字を検索する |
wcsrchr() |
ワイド文字の文字列を右から検索する |
wcslen() | ワイド文字の文字列の長さを取得する |
wscol() |
ワイド文字の文字列の表示幅を返す |
wcsspn() |
ワイド文字の文字列が別のワイド文字の文字列に現れる長さを返す |
wcscspn() |
ワイド文字の文字列が別のワイド文字の文字列に現れない長さを返す |
wcspbrk() |
別のワイド文字の文字列に含まれている、ワイド文字の文字列の先頭のポインタを返す |
wcstok() |
ワイド文字の文字列の中でトークンを移動する |
wscwcs() |
ワイド文字の文字列内の文字列を検索する |
wcstombs() |
ワイド文字の文字列を複数バイトの文字列に変換する |
wctomb() |
ワイド文字を複数バイト文字に変換する |
wcwidth() |
ワイド文字のカラム数を調べる |
wcswidth() |
ワイド文字の文字列のカラム数を調べる |
wctob() |
ワイド文字からシングルバイト文字に変換する |
wcrtomb() |
ワイド文字から文字に変換する (再起動可能) |
wcstol() |
ワイド文字の文字列をロング整数に変換する |
wcstoul() |
ワイド文字の文字列を符号なしロング整数に変換する |
wcstod() |
ワイド文字の文字列を倍精度に変換する |
wcsrtombs() |
文字列をワイド文字の文字列に変換する (再起動可能) |
wcscat() |
ワイド文字の文字列を照合する |
次の表に libc のワイド文字入力および出力の書式化関数を示します。
表 2–13 libc のワイド文字入力および出力の書式化関数
ライブラリルーチン |
説明 |
---|---|
wsprintf() |
書式に従ってワイド文字の文字列を生成する |
wsscanf() |
書式付き入力規約 |
fwprintf() |
ワイド文字書式付き出力を印刷する |
fwscanf() |
ワイド文字書式付き入力を変換する |
wprintf() |
ワイド文字書式付き出力を印刷する |
wscanf() |
ワイド文字書式付き入力を変換する |
swprintf() |
ワイド文字書式付き出力を印刷する |
swscanf() |
ワイド文字書式付き入力を変換する |
vfwprintf() |
stdarg 引数リストをワイド文字書式で出力する |
vswprintf() |
stdarg 引数リストをワイド文字書式で出力する |
次の表に libc のワイド文字列関数 API を示します。
表 2–14 libc ワイド文字列関数
ライブラリルーチン |
説明 |
---|---|
wscasecmp() |
大文字と小文字を区別せずにワイド文字の文字列を比較する |
wsncasecmp() |
コード文字列動作を処理する |
wcsstr() |
ワイド文字の部分文字列を検索する |
wmemchr() |
ワイド文字をメモリー内で検索する |
wmemcmp() |
メモリー内のワイド文字を比較する |
wmemcpy() |
メモリー内のワイド文字をコピーする |
wmemmove() |
領域がオーバーラップする状態でメモリー内のワイド文字をコピーする |
wmemset() |
メモリー内のワイド文字を設定する |
次の表に libc のワイド文字入力および出力関数を示します。
表 2–15 libc のワイド文字入力および出力関数
ライブラリルーチン |
説明 |
---|---|
fgetwc() |
ストリームから複数バイト文字を取り出し、ワイド文字に変換する |
getwchar() |
標準入力から複数バイト文字を取り出し、ワイド文字に変換する |
fgetws() |
ストリームから複数バイトの文字列を取り出し、ワイド文字に変換する |
getws() |
標準入力から複数バイト文字列を取り出し、ワイド文字に変換する |
fputwc() |
ワイド文字を複数バイト文字に変換し、ストリームに送る |
fwide() |
ストリームの方向を設定する |
putwchar() |
ワイド文字を複数バイト文字に変換し、標準入力に送る |
fputws() |
ワイド文字を複数バイトの文字列に変換し、ストリームに送る |
putws() |
ワイド文字を複数バイト文字列に変換し、標準入力に送る |
ungetwc() |
ワイド文字を入力ストリームに戻す |
新しい genmsg ユーティリティは、国際化されたソースメッセージカタログを作成するために、catgets() ファミリの関数で使用されます。このユーティリティは、ソースプログラムファイルの catgets での関数の呼び出しを調べ、見つかった情報からソースメッセージカタログを作成します。次の例を見てください。
% cat example.c ... /* NOTE: %s is a file name */ printf(catgets(catd, 5, 1, "%s cannot be opened.")); /* NOTE: "Read" is a past participle, not a present tense verb */ printf(catgets(catd, 5, 1, "Read")); ... % genmsg -c NOTE example.c The following file(s) have been created. new msg file = "example.c.msg" % cat example.c.msg $quote " $set 5 1 "%s cannot be opened" /* NOTE: %s is a file name */ 2 "Read" /* NOTE: "Read" is a past participle, not a present tense verb */
上記の例では、ソースファイル example.c について genmsg が実行され、example.c.msg という名前のソースメッセージカタログが作成されています。-c オプションの引数 NOTE により、genmsg はカタログにコメントを含めます。ソースプログラムのコメントに指定された文字列が含まれている場合、コメントはメッセージカタログの catgets の呼び出しから抽出された次の文字列の後に表示されます。
genmsg を使用して、メッセージセット内のメッセージの番号を自動的に付けることができます。
詳細については、genmsg(1) のマニュアルページを参照してください。
フォーマットされたメッセージカタログファイルを生成する場合は、gencat(1) ユーティリティを使用します。
Portable Message ファイル (.po ファイル) に対するメッセージ抽出ユーティリティと、.po ファイルからメッセージオブジェクトファイル (.mo ファイル) を生成する方法については、それぞれ xgettext(1) と msgfmt(1) のマニュアルページを参照してください。
Solaris ユーザーは、 geniconvtbl ユーティリティを使ってコードセットコンバータを定義できます。
このユーティリティを使えば、ユーザーが定義した、またはカスタマイズしたコードセット変換を iconv(1) や iconv(3C) などの標準的なシステムユーティリティやインタフェースを使って行うことができます。そのため、互換性のないデータ形式 (特にメーカー独自のアプリケーションや従来のアプリケーションのデータ) をアプリケーションで処理することが容易になります。既存の Solaris コードセット変換を変更することもできます。
詳細と例については、geniconvtbl(1) と geniconvtbl(4) のマニュアルページを参照してください。さらに、このユーティリティで使用する入力ソースファイルの例が /usr/lib/iconv/geniconvtbl/srcs/ ディレクトリにあります。
geniconvtbl(1) のマニュアルページの指定に従ってユーザーが定義したコード変換は、32 ビットおよび 64 ビット Solaris オペレーティング環境の iconv(1) ユーティリティや iconv(3C) 関数から使用することができます。