この章では,ロケールの作成方法について説明します。
ロケールは,母国語,文化的データ,オペレーティング・システム上のコードセットの特定の組み合わせをサポートするデータのセットです。
localedef
コマンドを使用して,以下のファイルからロケールを作成できます。
文字マップ・ソース・ファイル
charmap
(6.1 節)
このファイルのフォーマットや規則については,
charmap
(4)charmap
ファイルの例を示します。
またこの章では,シングルバイト文字とマルチバイト文字の両方を規定している SJIS コードセットの
charmap
ファイルの一部も示します。
ロケール・ソース・ファイル (6.2 節)
このファイルのフォーマットや規則については,
locale
(4)fr_FR.ISO8859-1@example
というロケールを作成します。
メソッド・ファイルおよび関連するシェアード・ライブラリ (6.3 節)
メソッド・ファイルとシェアード・ライブラリは,charmap
ファイルでマルチバイト文字を定義する際に必要です。
それ以外の場合,これらのファイルは省略可能です。
メソッド・ファイルには,ロケールが使用し,関連するシェアード・ライブラリ内で定義されている各関数のエントリが入っています。
メッセージ・ファイルのエントリには,ライブラリ名とパスが入っています。
メソッド・ファイルのエントリは,データ・コードと内部処理 (ワイド文字) コード間の変換を行う C ライブラリ・インタフェースの再定義を含むシェアード・ライブラリも指定します。
デスクトップ・アプリケーションで新しいロケールを使用するために変更しなければならないファイルの一覧は,第 5 章を参照してください。
6.1 ロケールに対応した文字マップ・ソース・ファイルの作成
charmap
ファイルは,文字のバイナリ・コードにシンボルを定義します。
localedef
コマンドは
charmap
ファイルを使用して,ロケール・ソース・ファイル内の文字シンボルを文字コードにマップします。
例 6-1
は,この章で作成する
fr_FR.ISO8859-1@example
ロケール用のソース・ファイル,ISO8859-1.cmap
の一部です。
D.1 節
には,このファイルの内容がすべて示されています。
例 6-1: サンプル・ロケール用の charmap ファイル
# [1] # Charmap for ISO 8859-1 codeset [1] # [1] <code_set_name> "ISO8859-1" [2] <mb_cur_max> 1 [2] <mb_cur_min> 1 [2] <escape_char> \ [2] <comment_char> # [2] CHARMAP [3] # Portable characters and other standard [1] # control characters [1] <NUL> \x00 [4] <SOH> \x01 <STX> \x02 <ETX> \x03 <EOT> \x04 <ENQ> \x05 <ACK> \x06 <BEL> \x07 <alert> \x07 <backspace> \x08 <tab> \x09 <newline> \x0a <vertical-tab> \x0b <form-feed> \x0c <carriage-return> \x0d <SO> \x0e
.
.
.
<zero> \x30 [4] <one> \x31 <two> \x32 <three> \x33 <A> \x41 <B> \x42 <C> \x43 <D> \x44
.
.
.
<underscore> \x5f [4] <low-line> \x5f <grave-accent> \x60 <a> \x61 <b> \x62 <c> \x63 <d> \x64
.
.
.
# Extended control characters [1] # (names taken from ISO 6429) [1] <PAD> \x80 [4] <HOP> \x81 <BPH> \x82 <NBH> \x83 <IND> \x84
.
.
.
# Other graphic characters [1] <nobreakspace> \xa0 [4] <inverted-exclamation-mark> \xa1
.
.
.
END CHARMAP [5]
コメント行
省略時のコメント文字は番号記号 (#) です。
省略時の指定は,<comment_char>
定義 (例 6-1
を参照) を使用して変更できます。
[例に戻る]
キーワード宣言
この例では,有効な宣言をすべて示し,<code_set_name>
を除くすべてのエントリに省略時の値を指定します。
一般に,省略時の値を変更したい場合にのみ,宣言を指定します。
この例では,<comment_char>
と
<escape_char>
宣言により,コメント文字とエスケープ文字の省略時の値を指定しています。
<mb_cur_max>
の値,つまりバイト単位での文字の最大の長さは,この
charmap
ファイルでは 1 です。
<mb_cur_min>
の値,つまりバイト単位での文字の最小の長さは,すべてのロケールの
charmap
ファイルで 1 でなければなりません (すべてのロケールには,シングルバイト文字を定義するポータブル文字セットの文字が含まれています)。
<code_set_name>
の値は,実行時にロケールにバインドされるアプリケーションから呼び出される
nl_langinfo(CODESET)
によって返される値になります。
[例に戻る]
文字マップの開始を示すヘッダ [例に戻る]
文字のシンボルからコードへのマップ
個々の文字マップは,シンボリック名とコード値から構成されます。 名前とコード値は,1 つ以上のスペースで区切られます。
シンボリック名は,左山カッコ (<) で始まり,右山カッコ (>) で終わります。
山カッコで囲まれる文字には,制御文字とスペース文字を除く,ポータブル文字セット中の任意の文字を使用できます。
名前に複数の右山カッコ (>) が含まれている場合,最後の山カッコを除くすべての山カッコの前に
<escape_character>
の値を付けなければなりません。
シンボリック名の長さは,128 バイトを超えることはできません。
コード値は,1 つまたは複数の 10 進数,8 進数,あるいは 16 進数の定数です (複数の定数はマルチバイトのコード値に対応します)。 定数のフォーマットは次のとおりです。
10 進数
\dnnn
または
\dnn
。
n
は 10 進数です。
16 進数
\xnn
。
n
は 16 進数です。
8 進数
\nnn
または
\nn
。
n
は 8 進数です。
同じ文字 (コード値) に対して (各々,異なるシンボリック名で) 複数の文字マップ・エントリを定義できます。 この例では,同じコード値に対して複数のシンボリック名は定義していません。 [例に戻る]
文字マップの終わりを示すトレイラ [例に戻る]
マルチバイト文字を含むコードセット用のソース・ファイルは,より複雑な文字マップを含みます。
例 6-2
は,日本語の SJIS コードセット用のソース・ファイルに含まれる文字マップ・エントリの一部です。
このソース・ファイルには,同じコードセット中でサポートしなければならない複数の文字セットのエントリが指定されています。
例 6-2: マルチバイト・コードセット用の charmap ファイルの一部
# SJIS charmap # <code_set_name> "SJIS" [1] <mb_cur_min> 1 [2] <mb_cur_max> 2 [3] CHARMAP # # CS0: ASCII #
.
.
.
<commercial-at> \x40 [4] <A> \x41 [4] <B> \x42 [4]
.
.
.
# # CS1: JIS X0208-1983 for ShiftJIS. # <zenkaku-space> \x81\x40 [5] <j0101>...<j0163> \x81\x40 [5] <j0164>...<j0194> \x81\x80 [5]
.
.
.
# # UDC Area in JIS X0208 plane # <u8501>...<u8563> \xeb\x40 [6] <u8564>...<u8594> \xeb\x80 [6] <u8601>...<u8663> \xeb\x9f [6]
.
.
.
# # CS2: JIS X0201 (so-called Hankaku-Kana) # <kana-fullstop> \xa1 [7]
.
.
.
<kana-conjunctive> \xa5 [7] <kana-WO> \xa6 [7] <kana-a> \xa7 [7]
.
.
.
END CHARMAP
コードセット名 [例に戻る]
1 文字の最小バイト数
この値は 1 でなければなりません。 [例に戻る]
1 文字の最大バイト数
SJIS では,マルチバイト文字の最大長は 2 バイトです。 [例に戻る]
ASCII 文字のシンボルとコード値 [例に戻る]
SJIS 文字のシンボルとコード値
文字シンボルを範囲として指定している点と,2 つの 16 進数値で 2 バイト文字のコード値を指定している点に注意してください。
シンボルがシンボル値の範囲として指定された場合,指定された文字コード値は,その範囲内の最初のシンボルに適用されます。
localedef
コマンドは,シンボル値とコード値の両方を自動的にインクリメントして,その範囲内のすべての文字のシンボル値とコード値を作成します。
[例に戻る]
SJIS コードセット中の UDC 用のマップ
これらのマップは,ユーザが後で文字を定義できるようにするための,コード値の範囲を設定します。 [例に戻る]
半角カナ文字セット用のシングルバイト文字のマップ [例に戻る]
文字マップ・ソース・ファイルに適用される規則の完全なリストについては,
charmap
(4)
注意
文字マップ・ソース・ファイル内の文字のシンボリック名に関しては,標準化作業が進行中です。 X/Open UNIX 標準の将来のリビジョンでは,文字に関して長いシンボリック名と短いシンボリック名の両方が規定される予定です。
この例の文字のシンボリック名は,必ずしも各種の標準化団体が提唱している名前と一致しているわけではではありません。
ロケール定義ソース・ファイルは,特定の言語と地域に固有のデータを定義します。 ソース・ファイルはセクションに分けられており,定義するロケール・データのカテゴリごとに 1 つのセクションがあります。 次のロケール・カテゴリがあります。
LC_CTYPE
。
文字クラスと属性を定義します (6.2.1 項)。
LC_COLLATE
。
文字や文字列の照合方法を定義します (6.2.2 項)。
LC_MESSAGES
。
肯定応答や否定応答に使用される文字列を定義します (6.2.3 項)。
LC_MONETARY
。
金額値の規則と記号を定義します (6.2.4 項)。
LC_NUMERIC
。
数値データの規則と記号を定義します (6.2.5 項)。
LC_TIME
。
日付と時刻を定義します (6.2.6 項)。
LC_ALL
。
すべてのカテゴリを指します。
例 6-3
に,ロケール定義ソース・ファイルの構成を擬似コードで示します。
例 6-3: ロケール・ソース定義ファイルの構成
# comment-line [1] comment_char <char_symbol1> [2] escape_char <char_symbol2> [3] CATEGORY_NAME [4] category_definition-statement [5] category_definition-statement [5]
.
.
.
END CATEGORY_NAME [6]
.
.
.
[7]
コメント行
番号記号 (#
) は,省略時のコメント文字です。
行の最初のカラムにコメント文字を置くことにより,その行全体をコメントとして指定できます。
ロケール・ソース・ファイル内では,定義文と同じ行にコメントを置くことはできません。
ロケール・ソース・ファイルは,この点で文字マップ・ソース・ファイルと異なります。
[例に戻る]
コメント文字の再定義
省略時のコメント文字は,comment_char
キーワードで始まり,その後に使用したいコメント文字のシンボルが続くエントリ行で置き換えることができます。
文字シンボルは,ロケールの文字マップ (charmap
) ソース・ファイルで定義されています。
[例に戻る]
省略時のエスケープ文字は,バックスラッシュ (\
) です。
この文字は,10 進,16 進,および 8 進の定数で使用され,定義文がソース・ファイルの次の行に続くことを示します。
省略時のエスケープ文字は,escape_char
キーワードで始まり,その後に 1 つまたは複数の空白文字,さらにその後に使用したいエスケープ文字のシンボルが続くエントリ行で置き換えることができます。
文字シンボルは,そのロケールの文字マップソース・ファイルで定義されています。
[例に戻る]
ロケール・カテゴリ・セクションのヘッダ
セクション・ヘッダは,LC_CTYPE
,LC_COLLATE
,LC_NUMERIC
,
LC_MONETARY
,LC_MESSAGES
,および
LC_TIME
の各カテゴリ名に対応しています。
[例に戻る]
カテゴリの定義文
これらの文のフォーマットは,カテゴリによって異なります。 一般に,定義文はキーワードで始まり,その後に 1 つまたは複数のスペースあるいはタブが続き,最後に定義そのものが続きます。
カテゴリ定義文の代りに
copy
文を記述して,他のロケール・ソース・ファイル内の定義文を取り込むことができます。
たとえば,次のように記述します。
copy en_US.ISO8859-1
copy
文を記述するときには,カテゴリ内には他の文を記述しないでください。
[例に戻る]
ロケール・カテゴリ・セクションのトレイラ
セクション・トレイラは
END
キーワードで始まり,その後にカテゴリ名が続きます。
[例に戻る]
すべてのロケール・カテゴリのセクションを含めることも,一部のカテゴリのセクションだけを含めることもできます。 ソース・ファイルでロケール・カテゴリのセクションを省略した場合,省略したカテゴリの定義は,省略時のロケール (POSIX または C ロケール) と同じになります。 [例に戻る]
以下の項では,特定のロケール・カテゴリに着目し,fr_FR.ISO8859-1@example.src
ロケール・ソース・ファイルの個々の部分について説明します。
D.2 節
に,このソース・ファイル全体を示しています。
6.2.1 LC_CTYPE ロケール・カテゴリの定義
ロケール・ソース・ファイルのLC_CTYPE
セクションは,文字クラスと,大文字と小文字の変換などの操作に使用される文字属性を定義します。
例 6-4
に,LC_CTYPE
セクションの定義を示します。
例 6-4: LC_CTYPE カテゴリの定義
############# LC_CTYPE [1] ############# upper <A>;<B>;<C>;<D>;<E>;<F>;<G>;<H>;<I>;<J>;<K>;<L>;<M>;\ <N>;<O>;<P>;<Q>;<R>;<S>;<T>;<U>;<V>;<W>;<X>;<Y>;<Z>;\ <A-grave>;\
.
.
.
<U-diaeresis> [2] lower <a>;<b>;<c>;<d>;<e>;<f>;<g>;<h>;<i>;<j>;<k>;<l>;<m>;\ <n>;<o>;<p>;<q>;<r>;<s>;<t>;<u>;<v>;<w>;<x>;<y>;<z>;\ <a-grave>;\
.
.
.
<u-diaeresis> [2] space <tab>;<newline>;<vertical-tab>;<form-feed>;\ <carriage-return>;<space> [2] cntrl <NUL>;<SOH>;<STX>;<ETX>;<EOT>;<ENQ>;<ACK>;\ <alert>;<backspace>;<tab>;<newline>;<vertical-tab>;\ <form-feed>;<carriage-return>;\
.
.
.
<SOS>;<SGCI>;<SCI>;<CSI>;<ST>;<OSC>;<PM>;<APC> [2] graph <exclamation-mark>;<quotation-mark>;<number-sign>;\
.
.
.
<u-circumflex>;<u-diaeresis>;<y-acute>;<thorn-icelandic>;<y-diaeresis> [2] # print class includes everything in the graph class above, plus <space>. print <exclamation-mark>;<quotation-mark>;<number-sign>;\
.
.
.
<u-circumflex>;<u-diaeresis>;<y-acute>;<thorn-icelandic>;<y-diaeresis>;\ <space> [2] punct <exclamation-mark>;<quotation-mark>;<number-sign>;\ <dollar-sign>;<percent-sign>;<ampersand>;<apostrophe>;\ <left-parenthesis>;<right-parenthesis>;<asterisk>;\ <plus-sign>;<comma>;<hyphen>;<period>;<slash>;\ <colon>;<semicolon>;<less-than-sign>;<equals-sign>;\ <greater-than-sign>;<question-mark>;<commercial-at>;\ <left-square-bracket>;<backslash>;<right-square-bracket>;\ <circumflex>;<underscore>;<grave-accent>;<left-brace>;\ <vertical-line>;<right-brace>;<tilde> [2] digit <zero>;<one>;<two>;<three>;<four>;\ <five>;<six>;<seven>;<eight>;<nine> [2] xdigit <zero>;<one>;<two>;<three>;<four>;\ <five>;<six>;<seven>;<eight>;<nine>;\ <A>;<B>;<C>;<D>;<E>;<F>;\ <a>;<b>;<c>;<d>;<e>;<f> [2] blank <space>;<tab> [2] toupper (<a>,<A>);(<b>,<B>);(<c>,<C>);(<d>,<D>);(<e>,<E>);\ (<f>,<F>);(<g>,<G>);(<h>,<H>);(<i>,<I>);(<j>,<J>);\ (<k>,<K>);(<l>,<L>);(<m>,<M>);(<n>,<N>);(<o>,<O>);\ (<p>,<P>);(<q>,<Q>);(<r>,<R>);(<s>,<S>);(<t>,<T>);\ (<u>,<U>);(<v>,<V>);(<w>,<W>);(<x>,<X>);(<y>,<Y>);\ (<z>,<Z>);\ (<a-grave>,<A-grave>);\ (<a-circumflex>,<A-circumflex>);\ (<ae-ligature>,<AE-ligature>);\ (<c-cedilla>,<C-cedilla>);\ (<e-grave>,<E-grave>);\ (<e-acute>,<E-acute>);\ (<e-circumflex>,<E-circumflex>);\ (<e-diaeresis>,<E-diaeresis>);\ (<i-circumflex>,<I-circumflex>);\ (<i-diaeresis>,<I-diaeresis>);\ (<o-circumflex>,<O-circumflex>);\ (<u-grave>,<U-grave>);\ (<u-circumflex>,<U-circumflex>);\ (<u-diaeresis>,<U-diaeresis>) [3] # tolower class is the inverse of toupper. tolower (<A>,<a>);(<B>,<b>);(<C>,<c>);(<D>,<d>);(<E>,<e>);\ (<F>,<f>);(<G>,<g>);(<H>,<h>);(<I>,<i>);(<J>,<j>);\ (<K>,<k>);(<L>,<l>);(<M>,<m>);(<N>,<n>);(<O>,<o>);\ (<P>,<p>);(<Q>,<q>);(<R>,<r>);(<S>,<s>);(<T>,<t>);\ (<U>,<u>);(<V>,<v>);(<W>,<w>);(<X>,<x>);(<Y>,<y>);\ (<Z>,<z>);\ (<A-grave>,<a-grave>);\ (<A-circumflex>,<a-circumflex>);\ (<AE-ligature>,<ae-ligature>);\ (<C-cedilla>,<c-cedilla>);\ (<E-grave>,<e-grave>);\ (<E-acute>,<e-acute>);\ (<E-circumflex>,<e-circumflex>);\ (<E-diaeresis>,<e-diaeresis>);\ (<I-circumflex>,<i-circumflex>);\ (<I-diaeresis>,<i-diaeresis>);\ (<O-circumflex>,<o-circumflex>);\ (<U-grave>,<u-grave>);\ (<U-circumflex>,<u-circumflex>);\ (<U-diaeresis>,<u-diaeresis>) [3] END LC_CTYPE [4]
セクション・ヘッダ [例に戻る]
文字クラスの定義
これらの定義は,文字クラスを表すキーワード (プロパティとも呼ぶ) で始まり,その後に 1 つまたは複数のブランク文字と,そのクラスに含まれるすべての文字シンボルのリストが続きます。 文字シンボルではなくコード値を指定することもできますが,その場合には,ロケール・ソース・ファイルの可読性が損われ,複数のコードセットで使用できなくなります。
例には示していませんが,水平方向の省略記号 (...
) を使用して文字の範囲を表すことができます。
たとえば文字列
<NUL>;...;<tab>
では,省略記号 (...
) は,コード値がシンボル
<NUL>
からシンボル
<tab>
までの範囲にあるすべての文字を表します。
シンボルとそのコード値は,そのロケールの
charmap
ファイルで定義されています。
X/Open UNIX 標準で定義された文字クラスは,次のキーワードで表します。
upper
(大文字の英字)
lower
(小文字の英字)
alpha
(すべての英字)
省略時の定義では,alpha
クラスは,upper
クラスと
lower
クラスの文字を合わせたものです。
サンプルのロケールでは
alpha
クラスを明示的に定義していないので,省略時の定義が適用されます。
space
(ホワイトスペース文字)
cntrl
(制御文字)
punct
(句読点)
digit
(数字)
xdigit
(16 進の数字)
blank
(空白文字)
graph
(スペース文字を除く印字可能文字)
省略時の定義では,このクラスは
alpha
,digit
,および
punct
クラスの文字を合わせたものです。
print
(スペース文字を含む印字可能文字)
省略時の定義では,このクラスは
alpha
,digit
,および
punct
クラスの文字と空白文字を合わせたものです。
アプリケーションの観点からは,alnum
というクラスも存在します。
このクラスは,alpha
クラスと
digit
クラスの文字を合わせたものと定義されているため,ロケールで定義されることは稀です。
Unicode (*.UTF-8
) ロケールは,Unicode 標準で定義されている文字クラスを含みます。
Unicode
の文字分類についての詳細は,
locale
(4)
日本語などのアジア系言語のロケールでは,標準以外の文字クラスも定義されています。 [例に戻る]
英字の大文字/小文字変換の定義
大文字/小文字変換の定義は,キーワード
toupper
と
tolower
で始まり,シンボルを個別に指定するのではなく対として指定します。
この例の
toupper
の定義では,対の最初のシンボルが英字の小文字を,2 番目のシンボルが英字の大文字を表します。
この定義は,関数
towupper()
と
towlower()
がテキスト・データの大文字/小文字変換を実行するときの,変換対象の英字を定義します。
標準以外の文字クラスを定義するロケールでは,wctrans()
と
towctrans()
関数が使用する,その他のプロパティ変換も定義される場合があります。
セクション・トレイラ [例に戻る]
上記の例は,LC_CTYPE
カテゴリを定義するときに使用できるすべてのオプションを示しているわけではありません。
その他のオプションを使用して,次の作業を行うこともできます。
copy
文を使用して,他のロケールのカテゴリ定義全体をインクルードする。
copy 文を使用するときは,copy
文がセクション・ヘッダとトレイラ間の唯一のエントリでなければなりません。
標準文字クラスのいずれかを省略したり,別の文字クラスを定義する。
標準の文字分類は言語によって異なります。 そのため,標準の文字クラスが適用できない言語もあります。 ロケールを定義する場合は,そのロケールの言語に適した標準の文字クラスだけを使用してください。 言語によっては,標準以外のクラス定義が必要になる場合があります。
標準以外の文字クラスを定義するには,そのクラスの前に
charclass
文でクラスのキーワードを定義して,その後にクラス定義を続けます。
次に例を示します。
charclass vowel vowel <a>;<e>;<i>;<o>;<u>;<y>
アプリケーションでは
wctype()
と
iswctype()
関数を使用して,すべての文字クラス (ユーザ定義の文字クラスも含む) を判別し,テストできます。
また,標準文字クラスのテストには,クラス固有の関数
iswalpha()
,iswpunct()
などを使用できます。
注意
fr_FR.ISO8859-1@example
ロケールのLC_CTYPE
カテゴリは,フランス語の文字に限定されています。 一部のロケール開発者は,ISO 8859-1 文字セットでサポートされているすべての言語の文字を含めた文字クラスを定義しようとします。 これによって,copy
文を使うことで,複数の西ヨーロッパ言語で同じLC_CTYPE
ソース定義を使用することができます。
LC_CTYPE
カテゴリの定義に適用されるその他の規則と制約については,
locale
(4)6.2.2 LC_COLLATE ロケール・カテゴリの定義
ロケール・ソース・ファイルの
LC_COLLATE
セクションには,文字と文字列の照合方法を指定します。
例 6-5
は,LC_COLLATE
セクションの一部です。
例 6-5: LC_COLLATE カテゴリの定義
LC_COLLATE [1] order_start forward;backward;forward [2] <NUL> [3] <SOH> <STX> <ETX> <EOT> <ENQ> <ACK> <alert> <backspace> <tab>
.
.
.
<APC> [3] <space> <space>;<space>;<space> <exclamation-mark> <exclamation-mark>;<exclamation-mark>;<exclamation-mark> <quotation-mark> <quotation-mark>;<quotation-mark>;<quotation-mark>
.
.
.
<a> <a>;<a>;<a> [3] <A> <a>;<a>;<A> <feminine> <a>;<feminine>;<feminine> <a-acute> <a>;<a-acute>;<a-acute> <A-acute> <a>;<a-acute>;<A-acute> <a-grave> <a>;<a-grave>;<a-grave> <A-grave> <a>;<a-grave>;<A-grave> <a-circumflex> <a>;<a-circumflex>;<a-circumflex> <A-circumflex> <a>;<a-circumflex>;<A-circumflex> <a-ring> <a>;<a-ring>;<a-ring> <A-ring> <a>;<a-ring>;<A-ring> <a-diaeresis> <a>;<a-diaeresis>;<a-diaeresis> <A-diaeresis> <a>;<a-diaeresis>;<A-diaeresis> <a-tilde> <a>;<a-tilde>;<a-tilde> <A-tilde> <a>;<a-tilde>;<A-tilde> <ae-ligature> <a>;<a><e>;<a><e> <AE-ligature> <a>;<a><e>;<A><E> <b> <b>;<b>;<b> <B> <b>;<b>;<B> <c> <c>;<c>;<c> <C> <c>;<c>;<C> <c-cedilla> <c>;<c-cedilla>;<c-cedilla> <C-cedilla> <c>;<c-cedilla>;<C-cedilla>
.
.
.
<z> <z>;<z>;<z> [3] <Z> <z>;<z>;<Z> UNDEFINED [4] order_end [5] END LC_COLLATE [6]
セクション・ヘッダ [例に戻る]
要素に照合重みを割り当てる文が記述されているセクションの開始を示す
order_start
キーワード
order_start
キーワードの行には,各ソート・パスに適用される,セミコロン (;) で区切られたソート・ディレクティブが続きます。
ソート・ディレクティブには次のキーワードを指定できます。
forward
,文字列の先頭から末尾に向かって比較操作を実行します。
backward
,文字列の末尾から先頭に向かって比較操作を実行します。
position
,照合重み
IGNORE
が適用されない文字列中の文字の相対位置を考慮して,比較操作を実行します。
つまり,照合重みが
IGNORE
でなく,文字列の先頭 (forward,position
) または末尾 (backward,position
) から最も短い距離にある文字が最初に照合されます。
ソート・ディレクティブに 2 つのキーワードを指定する場合,つまり,position
キーワードを
forward
または
backward
のいずれかと組み合わせて指定する場合,2 つのキーワードはコンマ (,) で区切ります。
position
キーワード自体は,ディレクティブ
forward,position
と同じ効果を持ちます。
ソート・ディレクティブの数は,それ以降の文で各照合要素に割り当てられる重みの数に対応します。
各ソート・ディレクティブと関連する重みのセットは,文字列比較の 1 回のパスあるいはレベルの情報を指定します。
1 番目のディレクティブは,文字列比較操作で 1 次重みが適用されるときに使用され,2 番目のディレクティブは操作で 2 次重みが適用されるときに使用されます (3 番目以降のディレクティブについても同様)。
文字列を正しく照合するのに必要なレベル数は,言語と文化習慣に依存するため,ロケールごとに異なります。
また,レベル数には,limits.h
と
sys/localedef.h
ファイルの
COLL_WEIGHTS_MAX
の設定によって決まる最大値があります。
Tru64 UNIX システムでは,最大照合レベル (ソート・ディレクティブ) は 6 に制限されています。
backward
ディレクティブは多くの言語で使用されるディレクティブであり,比較対象の文字列が等価な場合に,アクセントの付いた文字をアクセントの付かない文字の後に置くために使用します。
position
ディレクティブは,西ヨーロッパ言語のハイフン (-) のように,単語内での位置によって意味が変わる文字を扱うために頻繁に使用されます。
このディレクティブの使用例としては,"o-ring" という単語を単語リストの中で "or-ing" の前に並べたいが,ハイフンを考慮するのは,すべての文字列を英字だけでソートした後にしたい場合が挙げられます。
このような順序にソートするためには,2 つのソート・ディレクティブと,それに関連する重み指定子のセットが必要です。
最初の比較操作では,ソート・ディレクティブとして
forward
を指定し,すべての英字について英字を最初の重みとして使用して,ハイフン文字の重みとしては
IGNORE
を指定します。
2 回目,あるいはそれ以降の比較操作では,ソート・ディレクティブとして
forward position
を指定し,すべての英字について
IGNORE
を重みとして使用して,ハイフン文字の重みとしてハイフンを指定します。
ソート・ディレクティブを指定しない場合,省略時のディレクティブには
forward
が使用されます。
[例に戻る]
要素のための照合順序文
これらの文は,文字シンボルの後に,1 つまたは複数のブランク文字 (スペースまたはタブ) を指定し,さらにその後にソートの各段階で同じ重みを持つ文字のシンボルを指定します。
この例では,ソート順序は,制御文字,区切り文字と数字,英字の順です。 英字は複数のパスでソートされ,最初のパスでは判別記号と大文字/小文字の区別は無視され,2 番目のパスで判別記号が有効になり,3 番目のパスで大文字/小文字の区別が有効になります。 [例に戻る]
未定義文字のための照合順序文
UNDEFINED
キーワードは,ロケールの
charmap
ファイルでは定義されているが,他の照合順序文では指定されていないすべての文字に適用される照合順序文を開始します。
UNDEFINED
カテゴリに対応する文字は,正規表現では,同じ等価クラスに属するものと見なされます。
UNDEFINED
照合順序文は必ず指定しておきます。
指定しない場合には,localedef
コマンドは未定義文字を照合順序の最後に含め,警告を出します。
また,UNDEFINED
文を最後の照合順序文として指定すると,localedef
コマンドは,すべての未定義文字を 1 つのエントリに圧縮できる場合があります。
これにより,ロケールのサイズを小さくできます。
このロケールは,ロケールの
charmap
ファイルに指定された任意の (ただし,他の照合順序文で扱わない) 文字の照合順序を最後に位置づけるように指定します。
UNDEFINED
文は,オペランドを持つことができます。
たとえば,IGNORE
キーワードを指定すると,他の照合順序文に指定されていない文字は,IGNORE
が指定されているソート・パスで無視されます。
この例に次のような
UNDEFINED
文があったとすると,この文で指定されているソート・パスでは,他の照合順序文に指定されていない文字は無視されます。
UNDEFINED IGNORE;IGNORE;IGNORE
照合順序文の終わりを示すトレイラ [例に戻る]
LC_COLLATE
セクションの終わりを示すトレイラ
[例に戻る]
例 6-5
は,LC_COLLATE
カテゴリを定義するときに使用できるすべてのオプションを示しているわけではありません。
他のオプションを使用すると,次のような使い方も可能です。
copy
文を使用して,他のロケールのカテゴリ定義全体をインクルードする。
copy
文を使用するときは,copy
文がセクション・ヘッダとトレイラ間の唯一のエントリでなければなりません。
照合順序文で,照合要素として 1 つの文字ではなく,文字列を指定する。
その場合にはまず,order_start
文の前に
collating-element
文を指定して,文字列に対応するシンボルを定義します。
これにより,それらのシンボルを照合順序文で指定できるようになります。
次に例を示します。
collating-element <ch> from "<c><h>"
.
.
.
order_start forward;forward;backward
.
.
.
<ch> <Ch>;<ch>;<ch>
.
.
.
<UPPERCASE>
などのシンボリック名を,照合順序文で重み指定子として使用する。
order_start
文を指定する前に,ソース・ファイルで
collating-symbol
文を使用して個々のシンボリック名を定義しなければなりません。
次に,照合要素の照合順序文リストの適切な位置にそのシンボルを含めます。
たとえば,シンボル
<LOW>
を用いて照合順序の一番低い位置を示したい場合は,<LOW>
の行エントリを
order_start
文の直後に置きます。
<UPPERCASE>
などのシンボルは,大文字用の照合順序文のセクションの直前の行に置きます。
シンボルは,そのシンボルが使用される最初の照合順序文の前に置かなければなりません。 つまり,照合順序の一番高い位置にはシンボルを定義できません。
シンボルを定義し配置すると,照合順序文で重みとして使用できます。 次に例を示します。
collating-symbol <LOWERCASE> collating-symbol <UNACCENTED>
.
.
.
order_start forward;backward;forward;forward
.
.
.
<UNACCENTED>
.
.
.
<LOWERCASE> <a> <a>;<UNACCENTED>;<LOWERCASE>;IGNORE
.
.
.
Unicode ロケールと dense コード・ロケールは等価なため,Unicode ロケールと dense コード・ロケールの両方で同じ charmap とロケール・ソースを使用することができます。
ただし,charmap に定義されていて,LC_COLLATE
セクションに定義されていない Unicode 文字と dense コード文字は,異なる方法でソートされることがあります。
LC_COLLATE
カテゴリの定義についての詳細は,
locale
(4)6.2.3 LC_MESSAGES ロケール・カテゴリの定義
ロケール・ソース・ファイルの
LC_MESSAGES
セクションには,ユーザからの肯定応答と否定応答に使用する文字列を定義します。
例 6-6
は,LC_MESSAGES
セクションです。
例 6-6: LC_MESSAGES カテゴリの定義
LC_MESSAGES [1] # yes expression. The following designates: # "^([oO]|[oO][uU][iI])" yesexpr "<circumflex><left-parenthesis>\ <left-square-bracket><o><O><right-square-bracket>\ <vertical-line><left-square-bracket><o><O>\ <right-square-bracket><left-square-bracket><u><U>\ <right-square-bracket><left-square-bracket><i><I>\ <right-square-bracket><right-parenthesis>" [2] # no expression. The following designates: # "^([nN]|[nN][oO][nN])" noexpr "<circumflex><left-parenthesis>\ <left-square-bracket><n><N><right-square-bracket>\ <vertical-line><left-square-bracket><n><N>\ <right-square-bracket><left-square-bracket><o><O>\ <right-square-bracket><left-square-bracket><n><N>\ <right-square-bracket><right-parenthesis>" [3] # yes string. The following designates: "oui:o:O" yesstr "<o><u><i><colon><o><colon><O>" [4] # no string. The following designates: "non:n:N" nostr "<n><o><n><colon><n><colon><N>" [5] END LC_MESSAGES [6]
セクション・ヘッダ [例に戻る]
肯定応答として有効な表現の定義
このエントリは,yesexpr
キーワードと,その後に続く 1 つまたは複数のスペースあるいはタブ,さらにその後に続く二重引用符で区切られた拡張正規表現で構成します。
この表現は,このロケールでは "oui" や "o" (大文字/小文字は無視される) が有効な肯定応答であることを指定しています。
yesexpr
の正規表現は,ロケールの
charmap
ファイルで定義されているシンボルを用いて,個々の文字を指定しています。
[例に戻る]
否定応答として有効な表現の定義
このエントリは,noexpr
キーワードと,その後に続く 1 つまたは複数のスペースあるいはタブ,さらにその後に続く二重引用符で区切られた拡張正規表現で構成します。
この表現は,このロケールでは "non" や "n" (大文字/小文字は無視される) が有効な否定応答であることを指定しています。 [例に戻る]
肯定応答として有効な文字列の定義
このエントリは,yesstr
キーワードと,その後に続く 1 つまたは複数のスペースあるいはタブ,さらにその後に続く二重引用符で区切られた文字列で構成します。
X/Open の UNIX 標準では,yesstr
エントリは廃止される予定ですが,一部のアプリケーションやシステム・ソフトウェアではまだ,yesexpr
ではなく
yesstr
が使用されている可能性があります。
ロケールで
yesstr
を定義しておくことにより,そのようなソフトウェアでもロケールが使用できるようにしておくことが好ましい手法です。
X/Open UNIX 標準では
yesstr
に対して固定文字列を 1 つだけ定義しています。
複数の固定文字列を区切る区切り文字のコロン (:) は,標準仕様に対する拡張です。
[例に戻る]
否定応答として有効な文字列の定義
このエントリは,nostr
キーワードと,その後に続く 1 つまたは複数のスペースあるいはタブ,さらにその後に続く二重引用符で区切られた文字列で構成します。
X/Open の UNIX 標準では,nostr
エントリは廃止される予定ですが,一部のアプリケーションやシステム・ソフトウェアではまだ,noexpr
ではなく
nostr
が使用されている可能性があります。
ロケールで
nostr
を定義しておくことにより,そのようなソフトウェアでもロケールが使用できるようにしておくことが好ましい手法です。
X/Open UNIX 標準では
nostr
に対して固定文字列を 1 つだけ定義しています。
複数の固定文字列を区切る区切り文字のコロン (:) は,標準仕様に対する拡張です。
[例に戻る]
セクション・トレイラ [例に戻る]
シンボル定義を指定する代わりに,セクション・ヘッダとトレイラ間で
copy
文を使用して,既存のロケールの
LC_MESSAGES
カテゴリの定義をコピーできます。
copy
文はカテゴリの完全な定義であり,明示的なシンボル定義とともに使用することはできません。
6.2.4 LC_MONETARY ロケール・カテゴリの定義
ロケール・ソース・ファイルの
LC_MONETARY
セクションには,金額値の書式に使用する規則とシンボルを定義します。
アプリケーション開発者は
localeconv()
と
nl_langinfo()
関数を使用して,このセクションで定義されている情報を取得し,strfmon()
関数により書式規則を適用します。
例 6-7
は,LC_MONETARY
セクションです。
LC_MONETARY [1] int_curr_symbol "<F><R><F><space>" [2] currency_symbol "<F>" [2] mon_decimal_point "<comma>" [2] mon_thousands_sep "" [2] mon_grouping 3;0 [2] positive_sign "" [2] negative_sign "<hyphen>" [2]
.
.
.
END LC_MONETARY [3]
セクション・ヘッダ [例に戻る]
シンボル定義
上記の例のエントリは,次の指定を行います。
国際通貨記号は
FRF
(フランスのフラン) とし,国内通貨記号は
F
(フラン) とする。
コンマ (,
) を小数点文字とする。
ピリオド (.
) を小数点左側の千単位の区切り文字とする。
このロケールでは,小数点の左側の桁は 3 桁ごとにグループ化される。 このロケールでは省略時の 1000 単位の通貨区切りを定義していないため,このロケールで定義されている通貨のグループ区切りは,アプリケーションが 1000 単位の区切りを指定する関数を使用したときのみ有効になります。
正符号は付けない。
負符号はマイナス (-
) とする。
セクション・トレイラ [例に戻る]
LC_MONETARY
セクションで定義可能なシンボル名を,以下に示します。
int_curr_symbol
国際通貨記号
currency_symbol
国内通貨記号
mon_decimal_point
金額値の書式で使用する小数点文字
mon_thousands_sep
小数点左側の桁を区切るための文字
mon_grouping
小数点の左側で桁をグループ化する際の桁数。
mon_thousands_sep
で定義された文字がある場合は,mon_grouping
で定義されるグループの間にこの文字が挿入されます。
セミコロン (;) で区切って桁数を複数指定することで,グループの大きさを変化させることができます。
たとえば,3;2
と指定すると,小数点の左側の最初のグループは 3 桁になり,それに続くグループはすべて 2 桁になります。
Tru64 UNIX システムでは,3;0
と
3
は同じであり,小数点の左側のすべての桁は,3 桁ごとにグループ化されます。
positive_sign
金額が負でないことを表す文字列
negative_sign
金額が負であることを表す文字列
int_frac_digits
書式中に
int_curr_symbol
があるときに,小数点右側に置かれる桁数
frac_digits
書式中に
currency_symbol
があるときに,小数点右側に置かれる桁数
p_cs_precedes
国際通貨記号または国内通貨記号を,負でない金額の前に置くかどうかを決定する整数
p_sep_by_space
国際通貨記号または国内通貨記号を,負の金額書式の他の部分からスペース文字で区切るかどうかを決定する整数
n_cs_precedes
国際通貨記号または国内通貨記号を,負の金額書式の前に置くかどうかを決定する整数
n_sep_by_space
国際通貨記号または国内通貨記号を,負の金額書式の他の部分からスペース文字で区切るかどうかを決定する整数
p_sign_posn
負でない金額書式に正符号の文字列があるかどうかを判定し,ある場合にはその位置を示す整数
n_sign_posn
負符号の文字列が負の金額書式中に現れる位置を示す整数
シンボル定義を指定する代わりに,セクション・ヘッダとトレイラの間で
copy
文を使用して,既存のロケールの
LC_MONETARY
定義をコピーできます。
copy
文はカテゴリの完全な定義であり,明示的なシンボル定義とともに使用することはできません。
LC_MONETARY
の定義には,ユーロを完全にサポートしている UTF-8 および ISO8859-15 ロケールの言語のユーロ文字が設定されています。
ユーロ文字は Latin-1 に入っていないため,ISO8859-1 ロケールの言語は,ユーロを採用していても,ユーロより前の通貨記号を使用します。
たとえば,イタリア語のロケール
it_IT.ISO8859-15
は,ユーロをサポートします。
イタリア語のロケール
it_IT.ISO8859-1
は,リラをサポートします。
LC_MONETARY
シンボル定義についての詳細は,
locale
(4)6.2.5 LC_NUMERIC ロケール・カテゴリの定義
ロケール・ソース・ファイルの
LC_NUMERIC
セクションには,数値データを書式付けるための規則とシンボルを定義します。
localeconv()
と
nl_langinfo()
関数を使用することにより,この書式情報にアクセスできます。
例 6-8
は,LC_NUMERIC
セクションです。
LC_NUMERIC [1] decimal_point "<comma>" [2] thousands_sep "" [3] grouping 3;0 [4] END LC_NUMERIC [5]
カテゴリ・ヘッダ [例に戻る]
小数点文字の定義 [例に戻る]
小数点の左側の桁を区切るために使用する文字の定義。 このロケールでは,省略時の文字は定義されていません。 したがって,アプリケーションでは必要に応じてこの文字を指定する必要があります。 [例に戻る]
小数点の左側の桁の各グループの大きさ。
thousands_sep
で定義される文字があるときには,grouping
で定義されるグループの間に挿入されます。
セミコロン (;) で区切って桁数を複数指定することで,グループの大きさを変化させることができます。
たとえば,3;2
と指定すると,小数点の左側の最初のグループは 3 桁になり,それに続くグループはすべて 2 桁になります。
Tru64 UNIX システムでは,3;0
と
3
は同じであり,小数点の左側のすべての桁は,3 桁ごとにグループ化されます。
[例に戻る]
カテゴリ・トレイラ [例に戻る]
例 6-8
は,LC_NUMERIC
セクションで定義可能なすべてのシンボルを示します。
シンボル定義を使用する代わりに,セクション・ヘッダとトレイラ間に
copy
文を指定して,他のロケールからこのセクションをインクルードできます。
LC_NUMERIC
シンボル定義の詳細については,
locale
(4)6.2.6 LC_TIME ロケール・カテゴリの定義
ロケール・ソース・ファイルの
LC_TIME
セクションには,date
コマンドで使用されるフィールド記述子の解釈を定義します。
このカテゴリ・セクションは,strftime()
,wcsftime()
,strptime()
,および
nl_langinfo()
関数の動作に影響します。
例 6-9
に,サンプルのフランス語ロケールについて定義されているシンボルの一部を示します。
例 6-9: LC_TIME カテゴリの定義
LC_TIME [1] abday "<d><i><m>";\ "<l><u><n>";\ "<m><a><r>";\ "<m><e><r>";\ "<j><e><u>";\ "<v><e><n>";\ "<s><a><m>" [2] day "<d><i><m><a><n><c><h><e>";\ "<l><u><n><d><i>";\ "<m><a><r><d><i>";\ "<m><e><r><c><r><e><d><i>";\ "<j><e><u><d><i>";\ "<v><e><n><d><r><e><d><i>";\ "<s><a><m><e><d><i>" [3] abmon "<j><a><n>";\ "<f><e-acute><v>";\ "<m><a><r>";\ "<a><v><r>";\ "<m><a><i>";\ "<j><u><n>";\ "<j><u><l>";\ "<a><o><u-circumflex>";\ "<s><e><p>";\ "<o><c><t>";\ "<n><o><v>";\ "<d><e-acute><c>" [4] mon "<j><a><n><v><i><e><r>";\ "<f><e-acute><v><r><i><e><r>";\ "<m><a><r><s>";\ "<a><v><r><i><l>";\ "<m><a><i>";\ "<j><u><i><n>";\ "<j><u><i><l><l><e><t>";\ "<a><o><u-circumflex><t>";\ "<s><e><p><t><e><m><b><r><e>";\ "<o><c><t><o><b><r><e>";\ "<n><o><v><e><m><b><r><e>";\ "<d><e-acute><c><e><m><b><r><e>" [5] # date/time format. The following designates this # format: "%a %e %b %H:%M:%S %Z %Y" d_t_fmt "<percent-sign><a><space><percent-sign><e>\ <space><percent-sign><b><space><percent-sign><H>\ <colon><percent-sign><M><colon><percent-sign><S>\ <space><percent-sign><Z><space><percent-sign><Y>" [6]
.
.
.
END LC_TIME [7]
セクション・ヘッダ [例に戻る]
曜日の省略名
書式中にこの文字列を含めるには,%a
変換指定子を使用します。
[例に戻る]
曜日の完全名
書式中にこの文字列を含めるには,%A
変換指定子を使用します。
[例に戻る]
月の省略名
書式中にこの文字列を含めるには,%b
変換指定子を使用します。
[例に戻る]
月の完全名
書式中にこの文字列を含めるには,%B
変換指定子を使用します。
[例に戻る]
日付と時刻情報を組み合わせた書式
この書式では,strftime()
関数で定義されているように,フィールド記述子を結合します。
フィールド記述子の一覧については,
strftime
(3)
規定されている書式には,曜日の省略形 (%a
),月内の日付 (%e
),24 時間制での時間 (%H
),分 (%M
),秒 (%S
),タイム・ゾーン (%Z
),年の完全表現 (%Y
) のフィールド記述子があります。
米国東部時間で日付が 1999 年 4 月 23 日の場合,この例に指定された書式では,date
コマンドで
ven 23 avr 13:43:05 EDT 1999
と表示されます。
[例に戻る]
セクション・トレイラ [例に戻る]
例 6-9
は,LC_TIME
カテゴリのすべての標準シンボル定義を含んでいるわけではありません。
LC_TIME
では,次の標準の定義を指定することもできます。
d_fmt
日付だけの書式。
%x
フィールド記述子に対応します。
t_fmt
時刻だけの書式。
%X
フィールド記述子に対応します。
am_pm
午前と午後を表す文字列の書式。
%p
フィールド記述子に対応します。
たとえば,英語における定義は次のとおりです。
am_pm "<A><M>";"<P><M>"
t_fmt_ampm
12 時間制での時刻の書式。
%r
フィールド記述子に対応します。
era
era_d_fmt
元号表記での日付だけの書式。
%Ex
フィールド記述子に対応します。
era_t_fmt
元号表記での時刻だけの書式。
%EX
フィールド記述子に対応します。
era_d_t_fmt
元号表記での日付と時刻の両方を含む書式。
%Ec
フィールド記述子に対応します。
alt_digits
アジア各国のロケールで使用される数字の代替シンボルの定義。
%O
フィールド記述子に対応します。
この書式は,日付文字列に代替シンボルが含まれる国で使用します。
他のカテゴリ・セクションと同様に,copy
文を使用して,他のロケールの
LC_TIME
定義全体をインクルードできます。
Tru64 UNIX では,ここで説明したもの以外のシンボルとフィールド記述子もサポートしています。
LC_TIME
定義についての詳細は,
locale
(4)6.3 マルチバイト・コードとワイド文字コード間の変換を行うライブラリの構築
C ライブラリ・ルーチンは,データ・ファイル・コードとワイド文字コード (内部処理コード) 間の変換を行う特別なインタフェース群を使用します。 省略時には,C ライブラリ・ルーチンは,シングルバイト文字だけを扱うインタフェースを使用します。 ただし,多くのルーチンには,マルチバイト文字を扱える代替インタフェースを使用するためのエントリ・ポイントが用意されています。 ロケールのコードセットに合わせて修正可能なインタフェースはメソッドと呼ばれます。
マルチバイト・コードセットを持つロケールでは,メソッドを使用しなければなりません。 また,シングルバイト・コードセットのロケールでも,メソッドを用意しなければならない場合があります。 たとえば,ロケールに対応するインタフェースが文字のデータ形式の変換を行い,その操作を正しく実行するために,コードセット固有のロジックが必要になるロケールでは,メソッドを用意する必要があります。 ただし,対応するインタフェースがワイド文字に変換済みのデータを扱っており,シングルバイト文字とマルチバイト文字の両方に有効なロジックを使用しているときは,メソッドは無くてもかまいません。
ロケールにメソッドを用意する場合,必要なメソッドのセットを含んでいなければなりません (6.3.1 項を参照)。 オプションのメソッドについては,6.3.2 項を参照してください。
メソッドは,システム上ではシェアード・ライブラリとして利用できなければなりません。
このライブラリと,各メソッドを実装するライブラリ内の関数は,methods
ファイルを介して
localedef
コマンドから利用できるようになります。
localedef
コマンドで
methods
ファイルを
charmap
および
locale
ソース・ファイルとともに処理すると,結果として得られるロケールには,ロケールに含まれるすべてのメソッドへのポインタと,ロケールに含まれていない省略時のオプション・メソッドへのポインタが取り込まれます。
新たに作成したロケールを
LANG
変数に設定して,コマンドやアプリケーションを実行すると,メソッドは,システム・ソフトウェアで利用可能な状態になっていれば,常にコマンドやアプリケーションで使用されます。
6.3.1 必須メソッド
ロケールでメソッドを使用するときは,次のものが用意されていなければなりません。
_ _mbstopcs
(6.3.1.1 項)
_ _mbtopc
(6.3.1.2 項)
_ _pcstombs
(6.3.1.3 項)
_ _pctomb
(6.3.1.4 項)
mblen
(6.3.1.5 項)
mbstowcs
(6.3.1.6 項)
mbtowc
(6.3.1.7 項)
wcstombs
(6.3.1.8 項)
wctomb
(6.3.1.9 項)
wcswidth
(6.3.1.10 項)
wcwidth
(6.3.1.11 項)
これらのメソッドは,C ライブラリ関数でマルチバイト形式とワイド文字形式間のデータ変換を行えるようにします。
6.3.1.1 fgetws 関数用の _ _mbstopcs メソッドの作成
fgetws()
関数は
_ _mbstopcs
メソッドを使用して,標準入出力 (stdio
) バッファ内のバイトをワイド文字列に変換します。
このメソッドを実装する関数は,呼び出しによって変換されたワイド文字の数を返さなければなりません。
このメソッドは
mbstowcs()
(6.3.1.6 項を参照) に類似していますが,fgetws()
の要件を満たすために,いくつかのパラメータが追加されています。
一般に,このメソッドの C ソース・ファイルの名前は,_ _mbstopcs_codeset.c
です。
codeset
は,メソッドに対応するコードセットを示します。
例 6-10
は,ja_JP.sdeckanji
ロケールで使用される
_ _mbstopcs
メソッドを定義するファイル,_ _mbstopcs_sdeckanji.c
です。
例 6-10: ja_JP.sdeckanji ロケールのための _ _mbstopcs_sdeckanji メソッド
#include <stdlib.h> [1] #include <wchar.h> [1] #include <sys/localedef.h> [1] int _ _mbstopcs_sdeckanji( wchar_t *pwcs, [2] size_t pwcs_len, [3] const char *s, [4] size_t s_len, [5] int stopchr, [6] char **endptr, [7] int *err, [8] _LC_charmap_t *handle ) [9] { int cnt = 0; [10] int pwcs_cnt = 0; [10] int s_cnt = 0; [10] *err = 0; [11] while (1) { [12] if (pwcs_cnt >= pwcs_len || s_cnt >= s_len) { *endptr = (char *)&(s[s_cnt]); break; } [13] if ((cnt = _ _mbtopc_sdeckanji(&(pwcs[pwcs_cnt]), &(s[s_cnt]), (s_len - s_cnt), err)) == 0) { *endptr = (char *)&(s[s_cnt]); break; } [14] pwcs_cnt++; [15] if ( s[s_cnt] == (char) stopchr) { *endptr = (char *)&(s[s_cnt+1]); break; } [16] s_cnt += cnt; [17] } [18] return (pwcs_cnt); [19] }
このメソッドに必要な定数と構造体を含むヘッダ・ファイルをインクルードします。 [例に戻る]
ワイド文字列を格納しているバッファを
pwcs
でポイントします。
[例に戻る]
pwcs
バッファのサイズを格納するための変数
pwcs_len
を定義します。
[例に戻る]
変換対象のマルチバイト文字列を格納しているバッファを
s
でポイントします。
[例に戻る]
s
バッファ内のデータのバイト数を格納するための変数
s_len
を定義します。
fgetws()
関数が読み込む標準入出力バッファには,ヌルで終わる文字列が含まれていないため,このパラメータが必要になります。
[例に戻る]
変換を強制終了するためのバイト値を格納する変数
stopchr
を定義します。
一般に,この値は
\n
で,呼び出しごとに 1 行の入力を処理する
fgetws( )
関数からの呼び出しでこのメソッドに渡されます。
[例に戻る]
変換された最後のバイトの次のバイトをポイントする変数
endptr
を定義します。
このポインタは,fgetws()
の次の呼び出しに備え,標準入出力バッファ内の開始文字を指定するために必要です。
[例に戻る]
このメソッドが
mbtopc
メソッドを呼び出したときの実行ステータスを格納している変数を,err
でポイントします。
[例に戻る]
このロケールの文字マップを解析するメソッドへのポインタを格納している構造体を,hdl
でポイントします。
localedef
コマンドは
_LC_charmap_t
構造体を作成し,値を格納します。
[例に戻る]
マルチバイト形式の文字に必要なバイト数を示す変数 (mbtopc
メソッドが提供する) と,fgetws()
関数が使用するバッファ内のバイトまたは文字位置を示す変数を初期化します。
[例に戻る]
err
にゼロ (0) を設定し,成功を示します。
[例に戻る]
マルチバイト文字列を変換する
while
ループを開始します。
[例に戻る]
ワイド文字データを含むバッファ内にスペースがなくなるか,マルチバイト・データを含むバッファ内にデータがなくなったときに,endptr
を設定し,ループから抜けます。
[例に戻る]
mbtopc
メソッドを呼び出して,文字をマルチバイト形式からワイド文字形式に変換します。
mbtopc
メソッドが文字の変換に失敗し,エラーを返した場合,ループから抜け,変換できなかった文字の最初のバイトを
endptr
に設定します。
err
変数には,次のいずれかの,mbtopc
メソッド呼び出しのリターン・ステータスが格納されます。
0 は成功を示す。
-1 は無効な文字を示す。
0 より大きい値は,マルチバイト文字バッファに残っているバイト数が少ないため,有効な文字を作成できないことを示す。
この場合,有効な文字を作成するのに必要なバイト数が返されます。
この後,fgetws()
関数はバッファを再度充填し,処理をやり直します。
ワイド文字データを含むバッファ内の文字位置をインクリメントします。 [例に戻る]
マルチバイト・データ内に
stopchr
文字が現れた場合,endptr
を
stopchr
内の次の文字に設定します。
[例に戻る]
マルチバイト・データを含むバッファ内のバイト位置をインクリメントします。 [例に戻る]
while
ループを終了します。
[例に戻る]
ワイド文字データを含むバッファ内の文字数を返します。 [例に戻る]
getwc()
または
fgetwc()
関数は,_ _mbtopc
メソッドを呼び出して,マルチバイト文字をワイド文字に変換します。
このメソッドは,変換対象のマルチバイト文字に含まれるバイト数を返します。
このメソッドは
mbtowc
(6.3.1.7 項を参照) 用のメソッドと類似していますが,getwc()
が必要とするパラメータが追加されています。
一般に,このメソッドの C ソース・ファイルの名前は,_ _mbtopc_codeset.c
です。
codeset
は,このメソッドに対応するコードセットを示します。
例 6-11
は,ja_JP.sdeckanji
ロケールで使用される
_ _mbtopc
メソッドを定義しているファイル,_ _mbtopc_sdeckanji.c
です。
例 6-11: ja_JP.sdeckanji ロケールのための _ _mbtopc_sdeckanji メソッド
#include <stdlib.h> [1] #include <wchar.h> #include <sys/localedef.h> /* The algorithm for this conversion is: s[0] < 0x9f: PC = s[0] s[0] = 0x8e: PC = s[1] + 0x5f; s[0] = 0x8f PC = (((s[1] - 0xa1) << 7) | (s[2] - 0xa1)) + 0x303c s[0] > 0xa1:0xa1 < s[1] < 0xfe PC = (((s[0] - 0xa1) << 7) | (s[1] - 0xa1)) + 0x15e 0x21 < s[1] < 0x7e PC = (((s[0] - 0xa1) << 7) | (s[1] - 0x21)) + 0x5f1a +-----------------+-----------+-----------+-----------+ | process code | s[0] | s[1] | s[2] | +-----------------+-----------+-----------+-----------+ | 0x0000 - 0x009f | 0x00-0x9f | -- | -- | | 0x00a0 - 0x00ff | -- | -- | -- | | 0x0100 - 0x015d | 0x8e | 0xa1-0xfe | -- | JIS X0201 RH | 0x015e - 0x303b | 0xa1-0xfe | 0xa1-0xfe | -- | JIS X0208 | 0x303c - 0x5f19 | 0x8f | 0xa1-0xfe | 0xa1-0xfe | JIS X0212 | 0x5f1a - 0x8df7 | 0xa1-0xfe | 0x21-0xfe | -- | UDC +-----------------+-----------+-----------+-----------+ */ [2] int _ _mbtopc_sdeckanji( wchar_t *pwc, [3] char *ts, [4] size_t maxlen, [5] int *err, [6] _LC_charmap_t *handle ) [7] { wchar_t dummy; [8] unsigned char *s = (unsigned char *)ts; [9] if (s == NULL) return(0); [10] if (pwc == (wchar_t *)NULL) pwc = &dummy; [11] *err = 0; [12] if (s[0] <= 0x8d) { if (maxlen < 1) { *err = 1; return(0); } else { *pwc = (wchar_t) s[0]; return(1); } } [13] else if (s[0] == 0x8e) { if (maxlen >= 2) { if (s[1] >=0xa1 && s[1] <=0xfe) { *pwc = (wchar_t) (s[1] + 0x5f); return(2); } } else { *err = 2; return(0); } } [14] else if (s[0] == 0x8f) { if (maxlen >= 3) { if ((s[1] >=0xa1 && s[1] <=0xfe) && (s[2] >=0xa1 && s[2] <= 0xfe)) { *pwc = (wchar_t) (((s[1] - 0xa1) << 7) | (wchar_t) (s[2] - 0xa1)) + 0x303c; return(3); } } else { *err = 3; return(0); } } [15] else if (s[0] <= 0x9f) { if (maxlen < 1) { *err = 1; return(0); } else { *pwc = (wchar_t) s[0]; return(1); } } [16] else if (s[0] >= 0xa1 && s[0] <= 0xfe) { if (maxlen >= 2) { if (s[1] >=0xa1 && s[1] <= 0xfe) { *pwc = (wchar_t) (((s[0] - 0xa1) << 7) | (wchar_t) (s[1] - 0xa1)) + 0x15e; return(2); } else if (s[1] >=0x21 && s[1] <= 0x7e) { *pwc = (wchar_t) (((s[0] - 0xa1) << 7) | (wchar_t) (s[1] - 0x21)) + 0x5f1a; return(2); } } else { *err = 2; return(0); } } [17] *err = -1; return(0); [18] }
このメソッドに必要な定数と構造体を含むヘッダ・ファイルをインクルードします。 [例に戻る]
コードセットでサポートされる各種の文字セットについて,バイト数と有効バイトの組み合わせを判定するためのアルゴリズムを記述しています。
このコードセットは複数の文字セットをサポートしており,各文字セットに含まれる文字の長さは同じです。 最初のバイトの値から文字セットがわかり,同時に文字の長さも判定できます。 マルチバイト文字を含む文字セットでは,さらに 1 つまたは複数のバイトを調べ,値の並びが文字を表現しているか,無効なものかどうかを判定する必要があります。 [例に戻る]
ワイド文字を格納しているバッファを
pwc
でポイントします。
[例に戻る]
呼び出し元の関数からメソッドに渡されるバイトを格納しているバッファを,ts
でポイントします。
[例に戻る]
マルチバイト・データ内の最大バイト数を含む変数
maxlen
を宣言します。
この値は呼び出し元の関数から渡されます。 [例に戻る]
実行ステータスを含むバッファを
err
でポイントします。
[例に戻る]
このロケールの文字マップを解析するメソッドへのポインタを格納している構造体を,handle
でポイントします。
[例に戻る]
変数
dummy
を宣言します。
この変数を
pwc
に設定することにより,pwc
が有効なアドレスをポイントしていることが保証されます。
[例に戻る]
ts
(符号付き文字の配列) を
s
(符号なし文字の配列) にキャストします。
この操作を行うことにより,配列に整数値が格納されているときに,それらの値をインデックスで参照する際に起きる問題を回避できます。
コンパイラは,char
のような小さな符号付きデータ型を,int
のような大きな符号付きデータ型と比較するときに,値の符号拡張を行います。
この場合,次のような条件は,偽になると期待していても真と評価されます。
if (s[0] <= 0x8d
[例に戻る]
s
バッファが
NULL
を含んでいるか,NULL
をポイントしているときは,ゼロ (0) を返します。
[例に戻る]
ts
バッファが
NULL
を含んでいるか,NULL
をポイントしているときは,dummy
の内容をワイド文字バッファに格納します。
この操作により,*pwc
は常に有効なアドレスをポイントします。
有効なアドレスをポイントしておらず,ワイド文字が
pwc
に格納されていない場合,アプリケーションがこのポインタを参照すると,セグメンテーション違反が発生します。
[例に戻る]
err
にゼロ (0) を設定し,成功を示します。
[例に戻る]
文字が,コードセットで 0x8d 以下の値として定義されているシングルバイト文字の 1 つであるかどうかを判定します。
s
が文字を含んでいない場合,ゼロ (0) を返し,バイトの変換が行われなかったことを示します。
また,err
に 1 を設定し,有効な文字を作成するには 1 バイトが必要であることを示します。
バイト値がテスト範囲に含まれている場合,対応する処理コード値を
pwc
に移動して,変換したバイトの数を示すために 1 を返します。
[例に戻る]
文字が,コードセットで値 0x8e (第 1 バイト) と,0xa1 から 0xfe の範囲の値 (第 2 バイト) として定義されている 2 バイト文字の 1 つであるかどうかを判定します。
文字が条件を満たす場合,対応する処理コード値を
pwc
バッファに移動して,変換したバイトの数を示すために 2 を返します。
そうでなければ,ゼロ(0)を返し,変換が行われなかったことを示します。
また,err
に 2 を設定し,有効な文字を作成するには少なくとも 2 バイトが必要であることを示します。
[例に戻る]
文字が,コードセットで値 0x8f (第 1 バイト),0xa1 から 0xfe の範囲の値 (第 2 バイト),および 0xa1 から 0xfe の範囲の値 (第 3 バイト) として定義されている 3 バイト文字の 1 つであるかどうかを判定します。
文字が条件を満たす場合,対応する処理コード値を
pwc
バッファに移動し,変換したバイトの数を示すために 3 を返します。
そうでなければ,ゼロ (0) を返し,変換が行われなかったことを示します。
また,err
に 3 を設定し,有効な文字を作成するには少なくとも 3 バイトが必要であることを示します。
[例に戻る]
文字が,コードセットで 0x90 から 0x9f の範囲の値として定義されているシングルバイト文字の 1 つであるかどうかを判定します。
標準入出力バッファにバイト・データがない場合,ゼロ (0) を返し,変換が行われなかったことを示します。
また,err
に 1 を設定し,有効な文字を作成するには少なくとも 1 バイトが必要であることを示します。
バイト値が定義された範囲に含まれていれば,対応する処理コード値を
pwc
に移動し,変換したバイトの数を示すために 1 を返します。
[例に戻る]
文字が,コードセットで 0xa1 から 0xfe の範囲の値 (第 1 バイト) と,0x21 から 0x7e の範囲の値 (第 2 バイト) として定義されている 2 バイト文字の 1 つであるかどうかを判定します。
文字が条件を満たす場合,対応する処理コード値を
pwc
バッファに移動し,変換したバイトの数を示すために 2 を返します。
そうでなければ,ゼロ (0) を返し,変換が行われなかったことを示します。
また,err
に 2 を設定し,有効な文字を作成するには少なくとも 2 バイトが必要であることを示します。
[例に戻る]
err
に -1 を設定し,無効なマルチバイト・シーケンスが存在していたことを示します。
また,ゼロ (0) を返し,変換が行われなかったことを示します。
これらの文は,s
中のマルチバイト・データが,上記の
if
条件をいずれも満たしていない場合に実行されます。
[例に戻る]
fputws()
関数は
_ _pcstombs
メソッドを呼び出して,文字列を処理 (ワイド文字) コードからマルチバイト・コードに変換します。
このメソッドが -1 を返し,ロケールでサポートされていないことを示した場合,fputws()
は,変換する文字列中のワイド文字ごとに
putwc()
を呼び出します。
一般に,このメソッドの C ソース・ファイルの名前は,_ _pcstombs_codeset.c
です。
codeset
は,このメソッドに対応するコードセットを示します。
例 6-12
は,ja_JP.sdeckanji
ロケールで使用される
_ _pcstombs
メソッドを定義するファイル,_ _pcstombs_sdeckanji.c
です。
例 6-12: ja_JP.sdeckanji ロケールのための _ _pcstombs_sdeckanji メソッド
int _ _pcstombs_sdeckanji() { return -1; [1] }
-1 を返し,このメソッドがロケールでサポートされていないことを示します。
この戻り値により,fputws()
関数は
putwc()
を複数回呼び出して,文字列中のワイド文字を変換します。
[例に戻る]
単に -1 を返すだけではない完全なメソッドを実装したい場合には,関数が変換されたワイド文字の数を返すようにしなければなりません。 また,次の例に示すヘッダ・ファイルとパラメータをインクルードする必要があります。
#include <stdlib.h> #include <wchar.h> #include <sys/localedef.h> int _ _pcstombs_newcodeset( wchar_t *pcsbuf, [1] size_t pcsbuf_len, [2] char *mbsbuf, [3] size_t mbsbuf_len, [4] char **endptr, [5] int *err, [6] _LC_charmap_t *handle ) [7]
ワイド文字列を含むバッファへのポインタを指定します。 [例に戻る]
ワイド文字バッファの大きさを含む変数を指定します。
この値は,fputws()
からの呼び出しでメソッドに渡されます。
[例に戻る]
マルチバイト文字列を含むバッファへのポインタを指定します。 [例に戻る]
マルチバイト文字バッファの大きさを含む変数を指定します。
この値は,fputws()
からの呼び出しでメソッドに渡されます。
[例に戻る]
すべてのワイド文字データを変換するために
fputws()
を複数回呼び出さなければならない場合,マルチバイト文字バッファ内の次の文字の開始バイト位置へのポインタを,endptr
でポイントします。
[例に戻る]
実行ステータスを返すためのポインタを指定します。
このメソッドが文字変換を行うために
wctomb
メソッドを呼び出す場合,このステータスは
wctomb
が設定します。
それ以外の場合には,このメソッドはワイド文字からマルチバイト文字への変換を実行するロジックを備えている必要があり,また,このメソッドがステータスを直接設定しなければなりません。
いずれの場合でも,fputws()
関数は次の値を想定します。
成功時には 0。
ワイド文字の値が無効なため変換できない場合は -1。
最後の文字を処理した後で,マルチバイト文字バッファ内のバイト数が新しい文字を格納するのに足りない場合は正の値。
この場合,値は次の文字を格納するのに必要なバイト数です。
この後,fputws()
関数はマルチバイト文字バッファを空にして,再試行します。
このロケールで使用されるメソッドへのポインタを格納している
_LC_charmap_t
構造体へのポインタを指定します。
[例に戻る]
_ _pcstombs
メソッドは,_ _mbstopcs
メソッドが実行する操作 (6.3.1.1 項を参照) の逆の操作を行います。
データ変換の向きが異なるため,_ _pcstombs
メソッドには次のような特徴があります。
\n
などの変換停止文字のための変数を必要としない。
mbtowc
メソッドではなく
wctomb
メソッドを呼び出して (あるいは,wctomb
メソッドが行う操作を実装することにより),個々の文字を変換し,マルチバイト文字バッファ内でこのメソッドが必要とするバイト数を決定する。
C ライブラリ関数は,現時点では
_ _pctomb
インタフェースを使用しません。
たとえば
putwc()
関数は,wctomb
メソッドを呼び出して,文字をワイド文字形式からマルチバイト文字形式に変換します。
ただし,localedef
コマンドは,ロケールでメソッドが提供されている場合には,この関数のためのメソッドを必要とします。
一般に,このメソッドの C ソース・ファイルの名前は,_ _pctomb_codeset.c
です。
codeset
は,このメソッドに対応するコードセットを示します。
例 6-13
は,ja_JP.sdeckanji
ロケールで使用される
_ _pctomb
メソッドを定義するファイル,_ _pctomb_sdeckanji.c
です。
例 6-13: ja_JP.sdeckanji ロケールのための _ _pctomb_sdeckanji メソッド
int _ _pctomb_sdeckanji() { return -1; [1] }
-1 を返し,ロケールでこのメソッドがサポートされていないことを示します。 [例に戻る]
mblen()
関数は
mblen
メソッドを使用して,マルチバイト文字のバイト数を返します。
一般に,このメソッドの C ソース・ファイルの名前は,_ _mblen_codeset.c
です。
codeset
は,このメソッドに対応するコードセットを示します。
例 6-14
は,ja_JP.sdeckanji
ロケールで使用される
mblen
メソッドを定義するファイル,_ _mblen_sdeckanji.c
です。
例 6-14: ja_JP.sdeckanji ロケールのための _ _mblen_sdeckanji メソッド
#include <stdlib.h> [1] #include <wchar.h> #include <sys/errno.h> #include <sys/localedef.h> /* The algorithm for this conversion is: s[0] < 0x9f: 1 byte s[0] = 0x8e: 2 bytes s[0] = 0x8f 3 bytes s[0] > 0xa1 2 bytes +-----------------+-----------+-----------+-----------+ | process code | s[0] | s[1] | s[2] | +-----------------+-----------+-----------+-----------+ | 0x0000 - 0x009f | 0x00-0x9f | -- | -- | | 0x00a0 - 0x00ff | -- | -- | -- | | 0x0100 - 0x015d | 0x8e | 0xa1-0xfe | -- | JIS X0201 RH | 0x015e - 0x303b | 0xa1-0xfe | 0xa1-0xfe | -- | JIS X0208 | 0x303c - 0x5f19 | 0x8f | 0xa1-0xfe | 0xa1-0xfe | JIS X0212 | 0x5f1a - 0x8df7 | 0xa1-0xfe | 0x21-0xfe | -- | UDC +-----------------+-----------+-----------+-----------+ */ [2] int _ _mblen_sdeckanji( char *fs, [3] size_t maxlen, [4] _LC_charmap_t *handle ) [5] { const unsigned char *s = (void *) fs; [6] if (s == NULL || *s == '\0') return(0); [7] if (maxlen < 1) { _Seterrno(EILSEQ); return((size_t)-1); } [8] if (s[0] <= 0x8d) return(1); [9] else if (s[0] == 0x8e) { if (maxlen >= 2 && s[1] >=0xa1 && s[1] <=0xfe) return(2); } [10] else if (s[0] == 0x8f) { if(maxlen >=3 && (s[1] >=0xa1 && s[1] <=0xfe) && (s[2] >=0xa1 && s[2] <= 0xfe)) return(3); } [11] else if (s[0] <= 0x9f) return(1); [12] else if (s[0] >= 0xa1) { if (maxlen >=2 && (s[0] <= 0xfe) ) if ( (s[1] >=0xa1 && s[1] <= 0xfe) || (s[1] >=0x21 && s[1] <= 0x7e) ) return(2); } [13] _Seterrno(EILSEQ); return((size_t)-1); [14] }
このメソッドに必要な定数と構造体を含むヘッダ・ファイルをインクルードします。 [例に戻る]
文字のバイト数と,その文字が有効なバイト・シーケンスであるかどうかを決定するためのアルゴリズムを記述します。
このコードセットは複数の文字セットをサポートしており,各文字に含まれる文字の長さは同じです。 最初のバイトの値から文字セットがわかり,同時に文字の長さも判定できます。 マルチバイト文字を含む文字セットでは,さらに 1 つまたは複数のバイトを調べ,値の並びが文字を表現しているか,無効なものかどうかを判定する必要があります。 [例に戻る]
検査するバイト文字列を含むバッファを
fs
でポイントします。
[例に戻る]
マルチバイト文字の最大長を含む変数
maxlen
を定義します。
この値は,mblen()
関数からこのメソッドに渡されます。
[例に戻る]
このロケールの文字マップを解析するメソッドへのポインタを格納している構造体を,handle
でポイントします。
[例に戻る]
fs
(符号付き文字の配列) を
s
(符号なし文字の配列) にキャストします。
この操作を行うことにより,配列に整数値が格納されているときに,インデックスで参照する際に起きる問題を回避できます。
コンパイラは,char
のような小さな符号付きデータ型を,int
のような大きな符号付きデータ型と比較するときに,値の符号拡張を行います。
この場合,次のような条件は,偽になると期待していても真と評価されます。
if (s[0] <= 0x8d
[例に戻る]
s
が
NULL
を含んでいるか,NULL
をポイントしているときは,ゼロ (0) を返し,文字の長さがゼロ (0) であることを示します。
[例に戻る]
maxlen
(最大バイト数) がゼロか,負の値の場合には,-1 を返し,errno
に
[EILSEQ]
(無効な文字シーケンス) を設定します。
マルチスレッド・アプリケーションで
errno
が正しく機能するように設定するには,代入文ではなく
_Seterrno
を使用します。
[例に戻る]
最初のバイトが 0x8d 以下のシングルバイト文字を示しているかどうかを判定します。
そうであれば,1 を返して,文字の長さが 1 バイトであることを示します。 [例に戻る]
最初のバイトが値 0x8e を含み,2 番目のバイトが 0xa1 から 0xfe の範囲の値を含む 2 バイト文字を示しているかどうかを判定します。
そうであれば,2 を返して,文字の長さが 2 バイトであることを示します。 [例に戻る]
最初のバイトが値 0x8f を含み,2 番目と 3 番目のバイトが 0xa1 から 0xfe の範囲の値を含む 3 バイト文字を示しているかどうかを判定します。
そうであれば,3 を返して,文字の長さが 3 バイトであることを示します。 [例に戻る]
最初のバイトが 0x9f 以下のシングルバイト文字を示しているかどうかを判定します。
そうであれば,1 を返して,文字の長さが 1 バイトであることを示します。 [例に戻る]
最初のバイトが 0xa1 から 0xfe の範囲の値を含み,2 番目のバイトが 0x21 から 0x7e の範囲の値を含む 2 バイト文字を示しているかどうかを判定します。
そうであれば,2 を返して,文字の長さが 2 バイトであることを示します。 [例に戻る]
-1 を返し,errno
に
[EILSEQ]
を設定して,無効なマルチバイト・シーケンスであることを示します。
これらの文は,標準入出力バッファ内のマルチバイト・データが,上記の
if
条件をいずれも満たさない場合に実行されます。
[例に戻る]
mbstowcs()
関数は
mbstowcs
メソッドを使用して,マルチバイト文字列をプロセス・ワイド文字コードに変換し,結果として得られたワイド文字の数を返します。
一般に,このメソッドの C ソース・ファイルの名前は,_ _mbstowcs_codeset.c
です。
codeset
は,このメソッドに対応するコードセットを示します。
例 6-15
は,ja_JP.sdeckanji
ロケールで使用される
mbstowcs
メソッドを定義するファイル,_ _mbstowcs_sdeckanji.c
です。
例 6-15: ja_JP.sdeckanji ロケールのための _ _mbstowcs_sdeckanji メソッド
#include <stdlib.h> [1] #include <wchar.h> #include <sys/localedef.h> size_t _ _mbstowcs_sdeckanji( wchar_t *pwcs, [2] const char *s, [3] size_t n, [4] _LC_charmap_t *handle ) [5] { int len = n; [6] int rc; [7] int cnt; [8] wchar_t *pwcs0 = pwcs; [9] int mb_cur_max; [10] if (s == NULL) return (0); [11] mb_cur_max = MB_CUR_MAX; [12] if (pwcs == (wchar_t *)NULL) { cnt = 0; while (*s != '\0') { if ((rc = _ _mblen_sdeckanji(s, mb_cur_max, handle)) == -1) return(-1); cnt++ ; s += rc; } return(cnt); } [13] while (len-- > 0) { if ( *s == '\0') { *pwcs = (wchar_t) '\0'; return (pwcs - pwcs0); } if ((cnt = _ _mbtowc_sdeckanji(pwcs, s, mb_cur_max, handle)) < 0) return(-1); s += cnt; ++pwcs; } [14] return (n); [15] }
このメソッドに必要な定数と構造体を含むヘッダ・ファイルをインクルードします。 [例に戻る]
ワイド文字列を格納しているバッファを
pwcs
でポイントします。
[例に戻る]
マルチバイト文字列を格納しているバッファを
s
でポイントします。
[例に戻る]
pwcs
中のワイド文字数を含む変数
n
を定義します。
[例に戻る]
このロケールの文字マップを解析するメソッドへのポインタを格納している構造体を,handle
でポイントします。
[例に戻る]
pwcs
バッファ内のワイド文字の数 (呼び出し元関数が指定した
n
の値) を
len
に代入します。
[例に戻る]
このメソッドから呼び出される
mblen
関数が返す値を含む変数
rc
を定義します。
[例に戻る]
s
バッファ内の文字に使用されるバイト数をカウントする変数
cnt
を定義します。
[例に戻る]
呼び出し元の関数が
pwcs0
変数に渡すワイド文字列の開始点を保存します。
[例に戻る]
変数
mb_cur_max
を定義します。
この変数は後で
MB_CUR_MAX
に設定され,mblen
メソッドの呼び出しで使用されます。
[例に戻る]
s
が
NULL
の場合,ゼロ (0) を返します。
メソッドは,ロケールにおける文字のエンコーディングに状態がなければゼロ (0) を返し,状態があればゼロ以外の値を返します。 [例に戻る]
MB_CUR_MAX
に設定されている値を
mb_cur_max
に代入し,後で
mblen
メソッドの呼び出しに使用します。
[例に戻る]
NULL
ポインタが呼び出し元の関数から渡されたかどうかを調べ,渡されていれば
mblen
メソッドを呼び出してワイド文字列のサイズを計算します。
mbstowcs()
の呼び出しでヌル・ワイド文字を
pwcs
パラメータとして渡すことにより,メモリ割り当てに使用する
pwcs
バッファのサイズを取得できます。
また,この戻り値を使用することにより,再度
mbstowcs()
を呼び出してマルチバイト文字列を実際に変換する前に,アプリケーションのワイド文字バッファのメモリ・スペースを効率的に割り当てることができます。
[例に戻る]
ヌル文字 (文字列の終わり) が現れるまで
_ _mbtowc
メソッドを呼び出すことにより,マルチバイト文字バッファ内のバイトを変換します。
NULL が検出されたら処理を停止し,pwcs
バッファ内のワイド文字の数を返します。
文字の変換に成功するたびに,マルチバイト文字バッファ内のバイト位置を適切な数だけインクリメントします。
この
while
ループは,条件
len-- > 0
を使用して,pwcs
バッファが一杯になったときに処理を停止します。
ループ中の最初の
if
条件は,s
バッファ内のマルチバイト文字列がヌルで終了しているときに,pwcs
バッファ内の対応するヌル終端子が,mbtowcs()
関数によりアプリケーションに返されるワイド文字数に含まれないようにします。
[例に戻る]
n
の値を返して,pwcs
バッファ内のワイド文字の数を示します。
この文は,s
バッファ内でヌルが検出される前に,pwcs
バッファのスペースが足りなくなった場合に実行されます。
[例に戻る]
mbtowc()
関数は
mbtowc
メソッドを使用して,マルチバイト文字をワイド文字に変換し,変換したマルチバイト文字のバイト数を返します。
一般に,このメソッドの C ソース・ファイルの名前は,_ _mbtowc_codeset.c
です。
codeset
は,このメソッドが対応するコードセットを示します。
例 6-16
は,ja_JP.sdeckanji
ロケールで使用される
mbtowc
メソッドを定義するファイル,_ _mbtowc_sdeckanji.c
です。
例 6-16: ja_JP.sdeckanji ロケールのための _ _mbtowc_sdeckanji メソッド
#include <stdlib.h> [1] #include <wchar.h> #include <sys/errno.h> #include <sys/localedef.h> /* The algorithm for this conversion is: s[0] < 0x9f: PC = s[0] s[0] = 0x8e: PC = s[1] + 0x5f; s[0] = 0x8f PC = (((s[1] - 0xa1) << 7) | (s[2] - 0xa1)) + 0x303c s[0] > 0xa1:0xa1 < s[1] < 0xfe PC = (((s[0] - 0xa1) << 7) | (s[1] - 0xa1)) + 0x15e 0x21 < s[1] < 0x7e PC = (((s[0] - 0xa1) << 7) | (s[1] - 0x21)) + 0x5f1a +-----------------+-----------+-----------+-----------+ | process code | s[0] | s[1] | s[2] | +-----------------+-----------+-----------+-----------+ | 0x0000 - 0x009f | 0x00-0x9f | -- | -- | | 0x00a0 - 0x00ff | -- | -- | -- | | 0x0100 - 0x015d | 0x8e | 0xa1-0xfe | -- | JIS X0201 RH | 0x015e - 0x303b | 0xa1-0xfe | 0xa1-0xfe | -- | JIS X0208 | 0x303c - 0x5f19 | 0x8f | 0xa1-0xfe | 0xa1-0xfe | JIS X0212 | 0x5f1a - 0x8df7 | 0xa1-0xfe | 0x21-0xfe | -- | UDC +-----------------+-----------+-----------+-----------+ */ [2] int _ _mbtowc_sdeckanji( wchar_t *pwc, [3] const char *ts, [4] size_t maxlen, [5] _LC_charmap_t *handle ) [6] { unsigned char *s = (unsigned char *)ts; [7] wchar_t dummy; [8] if (s == NULL) return(0); [9] if (maxlen < 1) { _Seterrno(EILSEQ); return((size_t)-1); } [10] if (pwc == (wchar_t *)NULL) pwc = &dummy; [11] if (s[0] <= 0x8d) { *pwc = (wchar_t) s[0]; if (s[0] != '\0') return(1); else return(0); } [12] else if (s[0] == 0x8e) { if ( (maxlen >= 2) && ((s[1] >=0xa1) && (s[1] <=0xfe))) { *pwc = (wchar_t) (s[1] + 0x5f); /* 0x100 - 0xa1 */ return(2); } } [13] else if (s[0] == 0x8f) { if((maxlen >= 3) && (((s[1] >=0xa1) && (s[1] <=0xfe)) && ((s[2] >=0xa1) && (s[2] <= 0xfe)))) { *pwc = (wchar_t) (((s[1] - 0xa1) << 7) | (wchar_t) (s[2] - 0xa1)) + 0x303c; return(3); } } [14] else if (s[0] <= 0x9f) { *pwc = (wchar_t) s[0]; if (s[0] != '\0') return(1); else return(0); } [15] else if (((s[0] >= 0xa1) && (s[0] <= 0xfe)) && (maxlen >= 2)){ if (((s[1] >=0xa1) && (s[1] <= 0xfe))){ *pwc = (wchar_t) (((s[0] - 0xa1) << 7) | (wchar_t)(s[1] - 0xa1)) + 0x15e; return(2); } else if (((s[1] >=0x21) && (s[1] <= 0x7e))){ *pwc = (wchar_t) (((s[0] - 0xa1) << 7) | (wchar_t)(s[1] - 0x21)) + 0x5f1a; return(2); } } [16] _Seterrno(EILSEQ); return(-1); [17] }
このメソッドに必要な定数と構造体を含むヘッダ・ファイルをインクルードします。 [例に戻る]
文字のバイト数と,その文字が有効なバイト・シーケンスであるかどうかを判定するためのアルゴリズムを記述します。
このコードセットは複数の文字セットをサポートしており,各文字セットに含まれる文字の長さは同じです。 最初のバイトの値から文字セットがわかり,同時に文字の長さも判定できます。 マルチバイト文字を含む文字セットでは,さらに 1 つまたは複数のバイトを調べ,値の並びが文字を表現しているか,無効なものかどうかを判定する必要があります。 [例に戻る]
ワイド文字を含むバッファを
pwc
でポイントします。
[例に戻る]
マルチバイト文字形式の値を含むバッファを
ts
でポイントします。
[例に戻る]
マルチバイト文字の最大長を含む変数
maxlen
を定義します。
この値は呼び出し元の関数から渡されます。
値は,アプリケーション・プログラマが最初に行った呼び出しで,MB_CUR_MAX
に設定されています。
[例に戻る]
このロケールの文字マップを解析するメソッドへのポインタを格納している構造体を,handle
でポイントします。
[例に戻る]
ts
(符号付き文字の配列) を
s
(符号なし文字の配列) にキャストします。
この操作を行うことにより,配列に整数値が格納されているときに,インデックスで参照する際に起きる問題を回避できます。
コンパイラは,char
のような小さな符号付きデータ型を,int
のような大きな符号付きデータ型と比較するときに,値の符号拡張を行います。
この場合,次のような条件は,偽になると期待していても真と評価されます。
if (s[0] <= 0x8d
[例に戻る]
変数
dummy
を宣言します。
この変数を
pwc
に設定することにより,pwc
が有効なアドレスをポイントすることが保証されます。
[例に戻る]
s
が
NULL
を含んでいるか,NULL
をポイントしているときは,ゼロ (0) を返して,ロケールにおける文字のエンコーディングに状態がないことを示します。
NULL
ポインタが渡された場合,このメソッドは,ロケールにおける文字のエンコーディングに状態があるかどうかを示す値を返さなければなりません。
状態がある場合は,ゼロ以外の値を返します。
[例に戻る]
マルチバイト・データ・バッファの長さが 1 バイト未満であれば,size_t
にキャストされた -1 を返し,errno
に
[EILSEQ]
(無効なバイト・シーケンス) を設定します。
[例に戻る]
ts
バッファが
NULL
を含んでいるか,NULL
をポイントしているときは,dummy
の内容をワイド文字バッファに格納します。
この操作により,pwc
は常に有効なアドレスをポイントします。
この操作を行わないと,ワイド文字が
pwc
に格納されていないときにアプリケーションがこのポインタを参照した場合,セグメンテーション違反が発生します。
[例に戻る]
最初のバイトが,0x8d 以下のシングルバイト文字を示しているかどうかを判定します。
そうであれば,対応する処理コード値を
pwc
バッファに格納し,文字の長さが 1 バイトであることを示す 1 を返します。
[例に戻る]
最初のバイトが値 0x8e を含み,2 番目のバイトが 0xa1 から 0xfe の範囲の値を含む 2 バイト文字を示しているかどうかを判定します。
そうであれば,対応する処理コード値を
pwc
バッファに格納し,文字の長さが 2 バイトであることを示す 2 を返します。
[例に戻る]
最初のバイトが値 0x8f を含み,2 番目と 3 番目のバイトが 0xa1 から 0xfe の範囲の値を含む 3 バイト文字を示しているかどうかを判定します。
そうであれば,対応する処理コード値を
pwc
バッファに格納し,文字の長さが 3 バイトであることを示す 3 を返します。
[例に戻る]
最初のバイトの値が 0x9f 以下のシングルバイト文字を示しているかどうかを判定します。
そうであれば,対応する処理コード値を
pwc
バッファに格納し,文字の長さが 1 バイトであることを示す 1 を返します。
[例に戻る]
最初のバイトが 0xa1 から 0xfe の範囲の値を含み,2 番目のバイトが 0x21 から 0x7e の範囲の値を含む 2 バイト文字を示しているかどうかを判定します。
そうであれば,対応する処理コード値を
pwc
バッファに格納し,文字の長さが 2 バイトであることを示す 2 を返します。
[例に戻る]
-1 を返し,errno
に
[EILSEQ]
を設定して,無効なマルチバイト・シーケンスであることを示します。
これらの文は,s
バッファ内のマルチバイト・データが上記の
if
条件をいずれも満たさない場合に実行されます。
[例に戻る]
wcstombs()
関数は
wcstombs
メソッドを呼び出して,ワイド文字列をマルチバイト文字列に変換し,結果として得られたマルチバイト文字列のバイト数を返します。
一般に,このメソッドの C ソース・ファイルの名前は,_ _wcstombs_codeset.c
です。
codeset
は,このメソッドに対応するコードセットを示します。
例 6-17
は,ja_JP.sdeckanji
ロケールで使用される
wcstombs
メソッドを定義するファイル,_ _wcstombs_sdeckanji.c
です。
例 6-17: ja_JP.sdeckanji ロケールのための _ _wcstombs_sdeckanji メソッド
#include <stdlib.h> [1] #include <wchar.h> #include <limits.h> #include <sys/localedef.h> size_t _ _wcstombs_sdeckanji( char *s, [2] const wchar_t *pwcs, [3] size_t n, [4] _LC_charmap_t *handle ) [5] { int cnt=0; [6] int len=0; [7] int i=0; [8] char tmps[MB_LEN_MAX+1]; [9] if ( s == (char *)NULL) { cnt = 0; while (*pwcs != (wchar_t)'\0') { if ((len = _ _wctomb_sdeckanji(tmps, *pwcs)) == -1) return(-1); cnt += len; pwcs++; } return(cnt); } [10] if (*pwcs == (wchar_t)'\0') { *s = '\0'; return(0); } [11] while (1) { [12] if ((len = _ _wctomb_sdeckanji(tmps, *pwcs)) == -1) return(-1); [13] else if (cnt+len > n) { *s = '\0'; break; } [14] if (tmps[0] == '\0') { *s = '\0'; break; } [15] for (i=0; i<len; i++) { *s = tmps[i]; s++; } [16] cnt += len; [17] if (cnt == n) break; [18] pwcs++; [19] } [20] if (cnt == 0) cnt = len; [21] return (cnt); [22] }
このメソッドに必要な定数と構造体を含むヘッダ・ファイルをインクルードします。 [例に戻る]
このメソッドが呼び出し元の関数に渡すマルチバイト文字列を格納しているバッファを,s
でポイントします。
[例に戻る]
変換するワイド文字列を格納しているバッファを
pwcs
でポイントします。
[例に戻る]
マルチバイト文字列バッファ内の最大バイト数を格納する変数
n
を定義します。
この値は,呼び出し元の関数が指定します。 [例に戻る]
このロケールの文字マップを解析するメソッドへのポインタを格納している構造体を,handle
でポイントします。
[例に戻る]
変換された文字のバイト数 (len
) でインクリメントされる変数
cnt
を初期化します。
[例に戻る]
変換された文字の長さを含む変数
len
を初期化します。
[例に戻る]
変換した文字を一時的な記憶領域から
s
に移動するときに,各マルチバイト文字中のバイトに対するインデックスとして使用する変数
i
を初期化します。
[例に戻る]
wctomb
メソッドの呼び出しで返されるマルチバイト文字を格納している一時的なバッファ
tmps
を定義します。
[例に戻る]
呼び出し元の関数が
s
バッファに
NULL
を渡したかどうかを調べます。
NULL
が渡されている場合,wctomb
メソッドを呼び出して,マルチバイト文字バッファ内の変換された文字に必要なバイト数 (ヌル終端子は除く) を計算します。
wcstombs()
の呼び出しでヌル・バイトを
s
パラメータとして渡すことにより,メモリ割り当てに使用する
s
バッファのサイズを取得できます。
また,この戻り値を使用することにより,再度
wcstombs()
を呼び出してワイド文字列を実際に変換する前に,アプリケーションのワイド文字バッファのメモリ・スペースを効率的に割り当てることができます。
[例に戻る]
ゼロ (0) を返し,マルチバイト文字が得られなかったことを示します。
また,pwcs
が
NULL
をポイントしていれば,s
に
NULL
を設定します。
[例に戻る]
ワイド文字列中の文字を処理する
while
ループを開始します。
[例に戻る]
wctomb
メソッドを呼び出して,ワイド文字バッファ内の文字を変換します。
wctomb
が -1 を返したときは,-1 を返して,文字が無効であることを示します。
[例に戻る]
wctomb
が変換した文字のためのスペースが
s
になければ,s
の末尾に
NULL
を置き,while
ループを抜けます。
[例に戻る]
s
中で
NULL
が検出されときは,s
にヌル終端子を移動して,while
ループを抜けます。
[例に戻る]
現在のワイド文字が
NULL
でない場合,tmps
内の各バイトを
s
に追加します。
[例に戻る]
マルチバイト形式でこの文字が占めるバイト数 (len
) だけ,cnt
をインクリメントします。
[例に戻る]
処理されたバイト数が
n
(s
の最大バイト数) に等しいときは,ヌル終端子を追加せずに
while
ループを抜けます。
[例に戻る]
pwcs
をインクリメントし,変換する次のワイド文字をポイントするようにします。
[例に戻る]
個々のワイド文字を変換する
while
ループを終了します。
[例に戻る]
s
に 1 文字分のスペースがない場合は,ゼロ (0) を返すようにします。
[例に戻る]
結果として得られたマルチバイト文字列中のバイト数を返します。 [例に戻る]
wctomb()
関数は
wctomb
メソッドを呼び出して,ワイド文字をマルチバイト文字に変換し,結果として得られたマルチバイト文字のバイト数を返します。
一般に,このメソッドの C ソース・ファイルの名前は,_ _wctomb_codeset.c
です。
codeset
は,このメソッドに対応するコードセットを示します。
例 6-18
は,ja_JP.sdeckanji
ロケールのための
wctomb
メソッドを定義するファイル,_ _wctomb_sdeckanji.c
です。
例 6-18: ja_JP.sdeckanji ロケールのための _ _wctomb_sdeckanji メソッド
#include <stdlib.h> [1] #include <wchar.h> #include <sys/errno.h> #include <sys/localedef.h> /* The algorithm for this conversion is: PC <= 0x009f: s[0] = PC PC >= 0x0100 and PC <=0x015d: s[0] = 0x8e s[1] = PC - 0x005f PC >= 0x015e and PC <=0x303b: s[0] = ((PC - 0x015e) >> 7) + 0x00a1 s[1] = ((PC - 0x015e) & 0x007f) + 0x00a1 PC >= 0x303c and PC <=0x5f19: s[0] = 0x8f s[1] = ((PC - 0x303c) >> 7) + 0x00a1 s[2] = ((PC - 0x303c) & 0x007f) + 0x00a1 PC >= 0x5f1a and PC <=0x8df7 s[0] = ((PC - 0x5f1a) >> 7) + 0x00a1 s[1] = ((PC - 0x5f1a) & 0x007f) + 0x0021 +-----------------+-----------+-----------+-----------+ | process code | s[0] | s[1] | s[2] | +-----------------+-----------+-----------+-----------+ | 0x0000 - 0x009f | 0x00-0x9f | -- | -- | | 0x00a0 - 0x00ff | -- | -- | -- | | 0x0100 - 0x015d | 0x8e | 0xa1-0xfe | -- | JIS X0201 RH | 0x015e - 0x303b | 0xa1-0xfe | 0xa1-0xfe | -- | JIS X0208 | 0x303c - 0x5f19 | 0x8f | 0xa1-0xfe | 0xa1-0xfe | JIS X0212 | 0x5f1a - 0x8df7 | 0xa1-0xfe | 0x21-0xfe | -- | UDC +-----------------+-----------+-----------+-----------+ */ [2] int _ _wctomb_sdeckanji( char *s, [3] wchar_t wc, [4] _LC_charmap_t *handle ) [5] { if (s == (char *)NULL) return(0); [6] if (wc <= 0x9f) { s[0] = (char) wc; return(1); } [7] else if ((wc >= 0x0100) && (wc <= 0x015d)) { s[0] = 0x8e; s[1] = wc - 0x5f; return(2); } [8] else if ((wc >=0x015e) && (wc <= 0x303b)) { s[0] = (char) (((wc - 0x015e) >> 7) + 0x00a1); s[1] = (char) (((wc - 0x015e) & 0x007f) + 0x00a1); return(2); } [9] else if ((wc >=0x303c) && (wc <= 0x5f19)) { s[0] = 0x8f; s[1] = (char) (((wc - 0x303c) >> 7) + 0x00a1); s[2] = (char) (((wc - 0x303c) & 0x007f) + 0x00a1); return(3); } [10] else if ((wc >=0x5f1a) && (wc <= 0x8df7)) { s[0] = (char) (((wc - 0x5f1a) >> 7) + 0x00a1); s[1] = (char) (((wc - 0x5f1a) & 0x007f) + 0x0021); return(2); } [11] _Seterrno(EILSEQ); return(-1); [12] }
このメソッドに必要な定数と構造体を含むヘッダ・ファイルをインクルードします。 [例に戻る]
このメソッドが使用する変換アルゴリズムを記述します。
コードセットでサポートされる各文字セットは,ワイド文字 (処理コード) 値の一意の範囲に対応しています。 個々の文字セット中では,マルチバイト文字の長さは一定 (1,2 または 3 バイト) です。 そのため,個々のワイド文字が属している範囲は,マルチバイト形式の文字に必要なバイト数を示します。 ワイド文字値そのものは,その文字のマルチバイト形式における特定の値を決定します。 [例に戻る]
マルチバイト文字を含むバッファを
s
でポイントします。
[例に戻る]
ワイド文字を含む変数
wc
を定義します。
[例に戻る]
このロケールの文字マップを解析するメソッドへのポインタを格納している構造体を,handle
でポイントします。
[例に戻る]
s
が
NULL
をポイントするときは,ゼロ (0) を返して,文字の変換が行われなかったことを示します。
[例に戻る]
ワイド文字値が 0x9f 以下の場合,その値を配列
s
の最初のバイトに移動して,変換された文字の長さが 1 バイトであることを示す 1 を返します。
[例に戻る]
ワイド文字値が 0x0100 から 0x015d の範囲にあれば,値 0x8e を配列
s
の最初のバイトに移動し,計算した値を 2 番目のバイトに移動します。
2 を返して,変換された文字の長さが 2 バイトであることを示します。
[例に戻る]
ワイド文字値が 0x015e から 0x303b の範囲にあれば,計算した値を配列
s
の最初のバイトと 2 番目のバイトに移動します。
2 を返して,変換された文字の長さが 2 バイトであることを示します。
[例に戻る]
ワイド文字値が 0x303c から 0x5f19 の範囲にあれば,値 0x8f を配列
s
の最初のバイトに移動し,計算した値を 2 番目と 3 番目のバイトに移動します。
3 を返して,変換された文字の長さが 3 バイトであることを示します。
[例に戻る]
ワイド文字の値が 0x5f1a から 0x8df7 の範囲にあれば,計算した値を配列
s
の最初のバイトと 2 番目のバイトに移動します。
2 を返して,変換された文字の長さが 2 バイトであることを示します。
[例に戻る]
errno
に
[EILSEQ]
を設定し,-1 を返して,ワイド文字が無効であることを示します。
これらの文は,ワイド文字の値が上記の条件をいずれも満たさない場合に実行されます。 [例に戻る]
wcswidth()
関数は
wcswidth
メソッドを使用して,ワイド文字列を表示するのに必要なカラム数を判定します。
一般に,このメソッドの C ソース・ファイルの名前は,_ _wcswidth_codeset.c
です。
codeset
は,このメソッドに対応するコードセットを示します。
例 6-19
は,ja_JP.sdeckanji
ロケールに使用される
wcswidth
メソッドを定義するファイル,_ _wcswidth_sdeckanji.c
です。
例 6-19: ja_JP.sdeckanji ロケールのための _ _wcswidth_sdeckanji メソッド
#include <stdlib.h> [1] #include <wchar.h> #include <sys/localedef.h> /* The algorithm for this conversion is: PC <= 0x009f: s[0] = PC PC >= 0x0100 and PC <=0x015d: s[0] = 0x8e s[1] = PC - 0x005f PC >= 0x015e and PC <=0x303b: s[0] = ((PC - 0x015e) >> 7) + 0x00a1 s[1] = ((PC - 0x015e) & 0x007f) + 0x00a1 PC >= 0x303c and PC <=0x5f19: s[0] = 0x8f s[1] = ((PC - 0x303c) >> 7) + 0x00a1 s[2] = ((PC - 0x303c) & 0x007f) + 0x00a1 PC >= 0x5f1a and PC <=0x8df7 s[0] = ((PC - 0x5f1a) >> 7) + 0x00a1 s[1] = ((PC - 0x5f1a) & 0x007f) + 0x0021 +-----------------+-----------+-----------+-----------+ | process code | s[0] | s[1] | s[2] | +-----------------+-----------+-----------+-----------+ | 0x0000 - 0x009f | 0x00-0x9f | -- | -- | | 0x00a0 - 0x00ff | -- | -- | -- | | 0x0100 - 0x015d | 0x8e | 0xa1-0xfe | -- | JIS X0201 RH | 0x015e - 0x303b | 0xa1-0xfe | 0xa1-0xfe | -- | JIS X0208 | 0x303c - 0x5f19 | 0x8f | 0xa1-0xfe | 0xa1-0xfe | JIS X0212 | 0x5f1a - 0x8df7 | 0xa1-0xfe | 0x21-0xfe | -- | UDC +-----------------+-----------+-----------+-----------+ */ [2] int _ _wcswidth_sdeckanji( const wchar_t *wcs, [3] size_t n, [4] _LC_charmap_t *hdl ) [5] { int len; [6] int i; [7] if (wcs == (wchar_t *)NULL || *wcs == (wchar_t)NULL) return(0); [8] len = 0; [9] for (i=0; wcs[i] != (wchar_t)NULL && i<n; i++) { [10] if (wcs[i] <= 0x9f) len += 1; [11] else if ((wcs[i] >= 0x0100) && (wcs[i] <= 0x015d)) len += 1; [12] else if ((wcs[i] >=0x015e) && (wcs[i] <= 0x303b)) len += 2; [13] else if ((wcs[i] >=0x303c) && (wcs[i] <= 0x5f19)) len += 2; [14] else if ((wcs[i] >=0x5f1a) && (wcs[i] <= 0x8df7)) len += 2; [15] else return(-1); [16] } [17] return(len); [18] }
このメソッドに必要な定数と構造体を含むヘッダ・ファイルをインクルードします。 [例に戻る]
必要な表示幅を判定するためのアルゴリズムを記述します。
各文字の表示幅は,文字が属する文字セットに応じて 1 カラムまたは 2 カラムのいずれかです。 表示幅は,マルチバイト形式の文字のサイズとは異なります。 たとえば,3 バイト文字には 2 つの表示カラムが必要であり,2 バイト文字には 1 つまたは 2 つの表示カラムが必要です。 [例に戻る]
表示幅情報を必要とするワイド文字列を含むバッファを,wcs
でポイントします。
[例に戻る]
wcs
バッファの最大サイズを含む変数
n
を定義します。
[例に戻る]
このロケールの文字マップを解析するメソッドへのポインタを格納している構造体を,hdl
でポイントします。
[例に戻る]
バイトまたはカラム数で表示幅を保持する変数
len
を定義します。
[例に戻る]
ループ・カウンタとして使用する変数
i
を定義します。
[例に戻る]
wcs
が
NULL
を含んでいるか,NULL
をポイントしている場合は,ゼロ (0) を返します。
[例に戻る]
len
をゼロ (0) に初期化します。
[例に戻る]
wcs
バッファ内の各ワイド文字を処理し,ワイド文字ポインタをインクリメントする
for
ループを開始します。
[例に戻る]
現在のワイド文字の値が 0x9f 以下であれば,len
を 1 だけインクリメントします。
[例に戻る]
現在のワイド文字の値が 0x0100 から 0x015d の範囲にあれば,len
を 1 だけインクリメントします。
[例に戻る]
現在のワイド文字の値が 0x015e から 0x303b の範囲にあれば,len
を 2 だけインクリメントします。
[例に戻る]
現在のワイド文字の値が 0x303c から 0x5f19 の範囲にあれば,len
を 2 だけインクリメントします。
[例に戻る]
現在のワイド文字の値が 0x5f1a から 0x8df7 の範囲にあれば,len
を 2 だけインクリメントします。
[例に戻る]
-1 を返して,文字列に無効なワイド文字が含まれていることを示します。
この文は,文字列中の値が上記の条件をいずれも満たさない場合に実行されます。
呼び出し元の関数
wcswidth()
は,ワイド文字が印字不可能な場合にも -1 を返します。
ただし,この条件は呼び出し元関数のレベルで評価されるため,このメソッドが評価する必要はありません。
[例に戻る]
wcs
バッファ内のワイド文字を処理する
for
ループを終了します。
[例に戻る]
ワイド文字列を表示するのに必要なカラム数を示す
len
を返します。
[例に戻る]
wcwidth()
関数は
wcwidth
メソッドを使用して,ワイド文字を表示するのに必要なカラム数を判定します。
一般に,このメソッドの C ソース・ファイルの名前は,_ _wcwidth_codeset.c
です。
codeset
は,このメソッドに対応するコードセットを示します。
例 6-20
は,ja_JP.sdeckanji
ロケールで使用される
wcwidth
メソッドを定義するファイル,_ _wcwidth_sdeckanji.c
です。
例 6-20: ja_JP.sdeckanji ロケールのための _ _wcwidth_sdeckanji メソッド
#include <stdlib.h> [1] #include <wchar.h> #include <sys/localedef.h> /* The algorithm for this conversion is: PC <= 0x009f: s[0] = PC PC >= 0x0100 and PC <=0x015d: s[0] = 0x8e s[1] = PC - 0x005f PC >= 0x015e and PC <=0x303b: s[0] = ((PC - 0x015e) >> 7) + 0x00a1 s[1] = ((PC - 0x015e) & 0x007f) + 0x00a1 PC >= 0x303c and PC <=0x5f19: s[0] = 0x8f s[1] = ((PC - 0x303c) >> 7) + 0x00a1 s[2] = ((PC - 0x303c) & 0x007f) + 0x00a1 PC >= 0x5f1a and PC <=0x8df7 s[0] = ((PC - 0x5f1a) >> 7) + 0x00a1 s[1] = ((PC - 0x5f1a) & 0x007f) + 0x0021 +-----------------+-----------+-----------+-----------+ | process code | s[0] | s[1] | s[2] | +-----------------+-----------+-----------+-----------+ | 0x0000 - 0x009f | 0x00-0x9f | -- | -- | | 0x00a0 - 0x00ff | -- | -- | -- | | 0x0100 - 0x015d | 0x8e | 0xa1-0xfe | -- | JIS X0201 RH | 0x015e - 0x303b | 0xa1-0xfe | 0xa1-0xfe | -- | JIS X0208 | 0x303c - 0x5f19 | 0x8f | 0xa1-0xfe | 0xa1-0xfe | JIS X0212 | 0x5f1a - 0x8df7 | 0xa1-0xfe | 0x21-0xfe | -- | UDC +-----------------+-----------+-----------+-----------+ */ [2] int _ _wcwidth_sdeckanji( wint_t wc, [3] _LC_charmap_t *hdl ) [4] { if (wc == 0) return(0); [5] if (wc <= 0x9f) return(1); [6] else if ((wc >= 0x0100) && (wc <= 0x015d)) return(1); [7] else if ((wc >=0x015e) && (wc <= 0x303b)) return(2); [8] else if ((wc >=0x303c) && (wc <= 0x5f19)) return(2); [9] else if ((wc >=0x5f1a) && (wc <= 0x8df7)) return(2); [10] return(-1); [11] }
このメソッドに必要な定数と構造体を含むヘッダ・ファイルをインクルードします。 [例に戻る]
必要な表示幅を判定するためのアルゴリズムを記述します。
各文字の表示幅は,文字が属する文字セットに応じて 1 カラムと 2 カラムのいずれかです。 表示幅は,マルチバイト形式の文字のサイズとは異なります。 たとえば,3 バイト文字には 2 つの表示カラムが必要であり,2 バイト文字には 1 つまたは 2 つの表示カラムが必要です。 [例に戻る]
表示幅情報を必要とするワイド文字を含む
wc
変数を定義します。
[例に戻る]
このロケールの文字マップを解析するメソッドへのポインタを格納している構造体を,hdl
でポイントします。
[例に戻る]
ワイド文字バッファが空の場合,ゼロ (0) を返します。 [例に戻る]
ワイド文字値が 0x009f 以下の場合,1 を返します。 [例に戻る]
ワイド文字値が 0x0100 から 0x015d の範囲にあれば,1 を返します。 [例に戻る]
ワイド文字値が 0x015e から 0x303b の範囲にあれば,2 を返します。 [例に戻る]
ワイド文字値が 0x303c から 0x5f19 の範囲にあれば,2 を返します。 [例に戻る]
ワイド文字値が 0x5f1a から 0x8df7 の範囲にあれば,2 を返します。 [例に戻る]
ワイド文字の値が無効な場合,-1 を返します。
呼び出し元の関数
wcwidth()
は,ワイド文字が印字不可能な場合にも -1 を返します。
ただし,この条件は呼び出し元関数のレベルで評価されるため,このメソッドが評価する必要はありません。
[例に戻る]
ロケールには,必須メソッド (6.3.1 項
を参照) 以外のメソッドも含めることができます。
メソッド指定がないために省略時のメソッドが適用された場合,そのメソッドはオプションだと見なされます。
つまり,ロケールでメソッドを使用するが,特定のロケール・カテゴリに関連する関数や,その他のロケール関連の関数用のメソッドを用意していない場合,localedef
コマンドは,シングルバイト文字とマルチバイト文字の両方の処理コードを扱う省略時のメソッドを適用します。
オプションのメソッドを作成するためには,C ライブラリ・ルーチンの内部インタフェースについての詳細情報が必要になります。 この情報はベンダ独自の情報であり,変更される場合があります。 したがって,この項のオプション・メソッドの説明は,必須メソッドの説明と比べて不完全です。
まれなケースとして,オプションのメソッドをロケールに含めなければならないことがあります。 詳細は,最寄りの技術サポートにお問い合わせください。
LC_CTYPE
カテゴリ
towupper
towlower
wctype
iswctype
LC_COLLATE
カテゴリ
fnmatch
strcoll
strxfrm
wcscoll
wcsxfrm
regcomp
regexec
regfree
regerror
LC_MONETARY
カテゴリ,LC_NUMERIC
カテゴリ,または両方
localeconv
strfmon
LC_TIME
カテゴリ
strftime
strptime
wcsftime
LC_MESSAGES
カテゴリ
rpmatch
その他
nl_langinfo()
例 6-21
に,コンパイラとリンカのコマンド行を示します。
これらのコマンド行は,ja_JP.sdeckanji
ロケールで使用されるシェアード・ライブラリをメソッドのソース・ファイルから作成する際に必要です。
例 6-21: ja_JP.sdeckanji ロケールで使用されるメソッドのライブラリの作成
cc -std0 -c \ _ _mblen_sdeckanji.c _ _mbstopcs_sdeckanji.c \ _ _mbstowcs_sdeckanji.c _ _mbtopc_sdeckanji.c \ _ _mbtowc_sdeckanji.c _ _pcstombs_sdeckanji.c \ _ _pctomb_sdeckanji.c _ _wcstombs_sdeckanji.c \ _ _wcswidth_sdeckanji.c _ _wctomb_sdeckanji.c \ _ _wcwidth_sdeckanji.c ld -shared -set_version osf.1 -soname libsdeckanji.so -shared \ -no_archive -o libsdeckanji.so \ _ _mblen_sdeckanji.o _ _mbstopcs_sdeckanji.o \ _ _mbstowcs_sdeckanji.o _ _mbtopc_sdeckanji.o \ _ _mbtowc_sdeckanji.o _ _pcstombs_sdeckanji.o _ _pctomb_sdeckanji.o \ _ _wcstombs_sdeckanji.o _ _wcswidth_sdeckanji.o _ _wctomb_sdeckanji.o \ _ _wcwidth_sdeckanji.o \ -lc
シェアード・ライブラリについての詳細は,
cc
(1)ld
(1)6.3.4 ロケールに対応した methods ファイルの作成
methods
ファイルには,ロケールで使用されるメソッド・シェアード・ライブラリで定義されている各関数のエントリが含まれています。
関数が実行する操作は,メソッド・キーワードで識別されます。
メソッド・キーワードの後には,引用符で囲まれた関数の名前と,その関数を含むシェアード・ライブラリのパスが続きます。
例 6-22
に,ja_JP.sdeckanji
ロケールで使用されるメソッドのための
methods
ファイルのセクションを示します。
C ライブラリ・インタフェースの指定を変更したいときは,必須のメソッドのリストを定義する必要があるため,この例で示すように,methods
ファイルには個々の必須メソッドのエントリが含まれていなければなりません。
ja_JP.sdeckanji
ロケールではすべてのオプション・メソッドに対して,省略時の実装が使用されています。
そのため,この例にはオプション・メソッドのエントリは含まれていません。
例 6-22: ja_JP.sdeckanji ロケールのための methods ファイル
# sdeckanji.m [1] # <method_keyword> "<entry>" "<package>" "<library_path>" [1] METHODS [2] _ _mbstopcs "_ _mbstopcs_sdeckanji" "libsdeckanji.so" \ "/usr/shlib/libsdeckanji.so" [3] _ _mbtopc "_ _mbtopc_sdeckanji" "libsdeckanji.so" \ "/usr/shlib/libsdeckanji.so" [3] _ _pcstombs "_ _pcstombs_sdeckanji" "libsdeckanji.so" \ "/usr/shlib/libsdeckanji.so" [3] _ _pctomb "_ _pctomb_sdeckanji" "libsdeckanji.so" \ "/usr/shlib/libsdeckanji.so" [3] mblen "_ _mblen_sdeckanji" "libsdeckanji.so" \ "/usr/shlib/libsdeckanji.so" [3] mbstowcs "_ _mbstowcs_sdeckanji" "libsdeckanji.so" \ "/usr/shlib/libsdeckanji.so" [3] mbtowc "_ _mbtowc_sdeckanji" "libsdeckanji.so" \ "/usr/shlib/libsdeckanji.so" [3] wcstombs "_ _wcstombs_sdeckanji" "libsdeckanji.so" \ "/usr/shlib/libsdeckanji.so" [3] wcswidth "_ _wcswidth_sdeckanji" "libsdeckanji.so" \ "/usr/shlib/libsdeckanji.so" [3] wctomb "_ _wctomb_sdeckanji" "libsdeckanji.so" \ "/usr/shlib/libsdeckanji.so" [3] wcwidth "_ _wcwidth_sdeckanji" "libsdeckanji.so" \ "/usr/shlib/libsdeckanji.so" [3] END METHODS [4]
コメント行
これらの行は,methods
ファイルの名前と,メソッド・エントリのフォーマットを示します。
フォーマット中の
<package>
フィールドは無視されますが,ライブラリ・パスを指定するためには,何らかの文字列をこのフィールドに設定しておかなければなりません。
[例に戻る]
メソッド・エントリの開始を示すヘッダ [例に戻る]
必須メソッドのエントリ [例に戻る]
メソッド・エントリの終わりを示すトレイラ [例に戻る]
methods
ファイルのエントリの詳細については,
localedef
(1)6.4 ロケールの作成とテスト
localedef
コマンドを使用して,ソース・ファイルからロケールを作成します。
例 6-23
は,この章のほとんどの例で使用されているフランス語ロケールを作成するためのコマンド行です。
この例では,すべてのソース・ファイルがユーザの省略時のディレクトリに置かれており,作成されたロケールもそのディレクトリに置かれるものとします。
例 6-23: fr_FR.ISO8859-1@example ロケールの作成
% localedef -f ISO8859-1.cmap \ [1] -i fr_FR.ISO8859-1.src \ [2] fr_FR.ISO8859-1@example [3]
-f オプションは,文字マップ・ソース・ファイルを指定します。 [例に戻る]
-i オプションは,ロケール定義ソース・ファイルを指定します。 [例に戻る]
コマンドに指定する最後の引数は,ロケールの名前です。 [例に戻る]
ロケールをテストする場合,特に,そのロケールがシステム上にインストールされている標準ロケールに類似している場合は,そのロケール名に拡張子を付けます。
アットマーク (@
) 拡張子を付加した名前を使用することにより,言語,地域,およびコードセットに対して標準の文字列を指定でき,またテスト・ロケールを一意に識別できます。
この設定は,後でテスト・ロケールを,他のロケールが配置されているディレクトリ
/usr/lib/nls/loc
に移動する際に重要になります。
例 6-23
には,localedef
コマンドの 1 つの形式と,2,3 のオプションだけを示します。
localedef
(1)
以下に,重要な規則とオプションの要約を示します。
ロケールでメソッドが定義されている場合は,-m
オプションを付けて
methods
ファイルを指定しなければならない。
たとえば,ja_JP.sdeckanji
ロケールを作成するためのコマンド行には,例 6-22
に示すファイルを使用するために
-m sdeckanji.m
が指定されています。
デバッグを行うときは,-v
オプションを指定することにより,コマンドを詳細モードで実行できる。
このオプションを
-c
オプションとともに使用すると,ロケールに関して有用な情報を含む
.c
ファイルが作成されます。
省略時の設定では,ロケールは
/usr/lib/nls/loc
ディレクトリになければなりません。
テスト・ロケールを
/usr/lib/nls/loc
ディレクトリに移動する前にテストしたい場合は,LOCPATH
変数を設定し,ロケールが置かれているディレクトリを指定します。
その後で
LANG
環境変数を新しいロケールに設定すれば,コマンドやアプリケーションを使用してロケールを対話形式でテストできます。
例 6-24
は,date
コマンドを使用して,日付と時刻の形式をテストします。
例 6-24: LOCPATH 変数の設定とロケールのテスト
% setenv LOCPATH ~harry/locales
% setenv LANG fr_FR.ISO8859-1@example
% date
ven 23 avr 13:43:05 EDT 1999
注意
LOCPATH
変数は,X/Open の UNIX 標準で規定されている仕様の拡張であり,この仕様に準拠するすべてのシステムで認識されるわけではありません。
プログラムによっては,標準ロケールの名前とまったく同じ名前を持つシステム・ディレクトリにインストールされたサポート・ファイルが使用されています。
その場合,アプリケーション・ソフトウェアやシステム・ソフトウェア,あるいはその両方は,LANG
環境変数の値を使用して,サポート・ファイルが置かれているロケール固有のディレクトリを決定します。
LANG
または
LC_ALL
環境変数にロケール・ファイル名を直接指定した場合,アットマーク (@) サフィックスが付加されているロケール・ファイル名は,アプリケーションによっては無効な検索パスとなることがあります。
LANG
環境変数に標準のロケール名を指定し,ロケールのカテゴリ変数に異なるロケール名を指定することにより,この問題を回避する方法を次の例に示します。
指定しなければならないカテゴリ変数は,その適用範囲が作成したロケールと元のロケール間で異なっているものだけです。
% setenv LANG fr_FR.ISO8859-1 % setenv LC_CTYPE fr_FR.ISO8859-1@example % setenv LC_COLLATE fr_FR.ISO8859-1@example
.
.
.
% setenv LC_TIME fr_FR.ISO8859-1@example