iconvで文字コード変換できるパターン(コードセット・コンバーター)を生成するUNIXコマンド。(generate iconv table)
オプション | 説明 |
---|---|
-f | バイナリテーブルが既に存在していたら、(エラーにせずに)上書きする。 |
iconvでの文字コード変換は、具体的には「/usr/lib/iconv/geniconvtbl/binarytables」に置いてある“拡張子btのファイル”が使われる。
このbt(バイナリーテーブル)ファイルを生成するのがgeniconvtblコマンド。(Solaris)
> geniconvtbl from_code%to_code.srcこれを実行すると、ソースファイルと同じディレクトリに拡張子btのファイルが作られる。
> su - # cd /usr/lib/iconv/geniconvtbl/binarytables # ln -s /〜/original_iconv/from_code%to_code.bt . # exitシンボリックリンクを一度作っておけば、元の位置のファイルを何度更新しても大丈夫。(rootユーザー以外でも)
> iconv -f from_code -t to_code 変換元ファイル > 変換先ファイル
逆変換がしたければ、新しいバイナリテーブルを別途作る必要がある。
ソースのサンプル(?)は、「/usr/lib/iconv/geniconvtbl/srcs」に入っている。拡張子srcのファイル。
この内容はC言語風の独自言語。おおまかに、次のような構造をしている。
構造 | 説明 | |||
---|---|---|---|---|
マクロ定義 | #defineや#include。省略可能 | |||
from_code%to_code { | 変換元コード名称と変換先コード名称 | |||
サブルーチン定義 | サブルーチン定義。省略可能 | |||
direction { | 変換定義 | |||
条件 | 変換内容 | コードをどのように変換するかを記述。 条件:conditionやtrue 変換内容:operationやmap |
||
(複数記述可) | ||||
}; | ||||
} |
「//」で行コメント。
// // geniconvtbl sample src // #include <sys/errno.h> #define A_END 0x52 from_code%to_code { //コード名称 operation sub { //サブルーチン定義 output = input[0] + s; discard; }; direction { condition { between 0x30...0x39; //入力バイト列の処理位置の1バイトが0x30〜0x39のとき } operation { output = input[0] | 0xf0; //入力バイトにf0の論理和をとって出力 // Move input buffer pointer one byte. discard; //入力の処理位置を後ろにずらす } condition { between 0x41...A_END; } operation { if (input[0] <= 0x49) { s = 0x80; } else { s = 0x87; } operation sub; //サブルーチン呼び出しの例 }; condition { between 0x20...0x29; } map { default 0x6f //下記以外は0x6fを出力 0x20 0x40 //入力バイトが0x20だったら0x40を出力 0x22 0x7f 0x23 0x7b 0x25 0x6c 0x26 0x50 0x27 0x7d 0x28 0x4d 0x29 0x5d }; true operation { //上記以外の入力だった場合 //output = input[0]; //discard; error EILSEQ; //エラーを発生させる }; }; }
マクロ定義には#defineを使用する。→例
#define VAR 0x00
定義したマクロ名は、between条件や変数への代入やエラーコードなどに使用できる。
#includeを使うと、C言語のヘッダーファイルがそのまま読み込まれるっぽい。→例
そのヘッダーファイルの中に書かれている#defineが使えるようになるっぽい。
#include <sys/errno.h>
「sys/errno.h」の中にはEILSEQ・E2BIG・EINVALといったマクロ(エラーコード)が定義されている。
こういったコードを使わないのであれば、#include自体不要。
変換元のコード名称と変換後のコード名称を「%」で区切って記述する。→例
その後ろに「{ }」でくくったブロックを作り、その中に変換内容を記述していく。
サブルーチンを定義することが出来る。→例
サブルーチンを使わないなら、定義不要。
operation サブルーチン名 { 内容; };
サブルーチン名が「init」だと、初期処理として最初に呼ばれるらしい。
グローバル変数の初期化に使える。
operation init { cs = 0; };
サブルーチンの呼び出しも、同じくoperationを使用する。
「{ };」でくくったブロックを作り、その中に条件と変換方法を記述していく。→例
入力文字列(バイト列)に対し、条件を指定する。
その条件にマッチすれば、直後の処理を行う。
condition { 条件式 } 処理;
条件式で最もよく使われるのがbetween。入力バイト列の現在の位置の文字(バイト)に対してコードの範囲を指定する。→例
condition { between 0x00...0x7f; } 処理;
between 0x41...0x5a, 0x61...0x7a;
between 0x41...0x5a, 0x61...0x7a;
2バイト以上をbetween条件にすることも出来る。
between 0x0041...0x005a;
入力の処理位置にあるバイト列が「00 41」であればマッチするが、「41」のみだとマッチしない。
C言語等の他の言語から見れば0x41と0x0041は同じだが、geniconvtblではマッチするバイト数が異なるので要注意!
条件式には変数の比較も使える。
condition { cs == 0; } 処理;
また、無条件に実行したい場合は(conditionの代わりに)trueを使う。→例
directionの一番最後で使えば、「その他全て」を実現できる。
true 処理;
変換処理を具体的に記述する。operationとmapの2通りの書き方が存在する。
operationは、プログラム的な文を記述する。→例
変数への代入や、if文(変数値の比較)や演算が出来る。
変数はグローバル変数で、特に定義しなくても使える。代入せずに使用すると 初期値として0が入っているっぽい。
operation { if (cs == 0) { cs = 1; } output = input[0] & 0x7f; };
特殊な変数としてinput、outputがある。
input[0]は、現在処理中の1バイト目を指す。input[1]が2バイト目、input[2]が3バイト目。→例
(1バイトのbetweenは、input[0]と比較していると言えよう)
outputに値を代入すると、出力になる。→例
output = 0x00; ←00を1バイト出力 output = 0x0000; ←00を2バイト出力
discardで、入力バイト列の処理位置を1バイト後ろへずらす。→例
「discard 2;」で、2バイトずらす。
// Move input buffer pointer two bytes. discard 2;
error E2BIG;
E2BIGは、#include <sys/errno.h>で読み込まれたマクロ。
どういうときにどういう値を返すべきかは、iconv(3C)のマニュアルに載っている。
エラーを発生させると、iconvがエラー終了する。ただしiconvのエラー時のリターンコードは1のみなので、error文で何を返しても
あまり意味が無い。
「operation サブルーチン名;」で、サブルーチンを呼び出す。→例
サブルーチンの中にもプログラムを書ける。
map { 入力値 変換値 … };
map {
0x30 0xf0 …0x30を0xf0に変換する
0x31 0xf1
0x32 0xf2
};
map {
0x30...0x39 0x00 …範囲指定。0x30〜0x39を全て0x00に変換する
};
map {
default 0x00 …「その他」はdefaultで表す
0x30...0x39 0xff
};
map {
0x12 0x0012 …1バイトの0x12を0x0012(2バイト)に変換する
};
map {
0x0012 0x12 …2バイトの0x0012を0x12(1バイト)に変換する
};