4. 文字テーブル
  1.9x 系以降の skf では、文字テーブルは以下の四種類に分けられる。
  
  (1) 入力に使い、skf バイナリ標準組み込みのもの
  (2) 出力に使い、skf バイナリ標準組み込みのもの
  (3) 入力に使い、skf バイナリ標準組み込みではないもの
  (4) 出力に使い、skf バイナリ標準組み込みではないもの
  
  以下、順に管理について説明する。
  
4.1 コード設定の流れ
  skf では、入出力のコードセットは以下の条件で決められる。
  
  (1) 出力コードセットは、コマンドラインで決まる。コマンドラインで指定値がないときは出力コードセットの既定値となる。既定値はコンパイル時に決まり、配布パッケージでは　EUC-JP-OPEN である。現時点のバイナリの既定値は、skf -v で知ることができる。
  (2) 入力コードセットは、コマンドライン指定、または指定がない場合は自動判定で決まる。入力判定で決まらない場合は、入力コードセットの既定値となる。現時点のバイナリの既定値は、skf -v で知ることができる。
  
  内部では、コマンドライン処理終了後、出力コードセットに関する初期化処理と言語のセット (および、必要なテーブルの読み込み) を行い、それに伴って設定されたパラメータ環境下で preconvert を実行、最終的に得られた入力コードセットに関する初期化処理および必要なテーブルの読み込み、パラメータのセットなどを行う。処理手順は以下の通り。
  
  (o1) skf.c 中で、out_codeset を確定させる
  (o2) skf.c 中から出力の所定のテーブルの読み込みを実施 (skf_charset_parser())
  (o3) skf.c から所定のテーブルの書き換えを実施 (skf_output_table_set())
  (o4) skf.c から未定義文字定義をおこなう (oconv_init())
  (o5) skf.c から announce を出力 (print_announce)
  
  (c) 入力をオープンして preconvert() を呼ぶ -
  
  (i1) preconvert 中 (実際には終了処理) で、入力の所定のテーブルの読み込みを実施
  (i2) preconvert 中で、必要な場合にはオーバレイテーブルを読み込む。
  (i3) preconvert 中で、必要なテーブルの書き換えを行う。
  (i4) 必要により、*_in() 中で変換に使うパラメータの設定を行う。
  (i5) 変換実施。変換終了文字 (EOF か行終了か MIME 開始/末尾) に当たった場合は (c) に戻る

  出力コードセットが動的に生成される場合には、さらに生成時に必要な charset テーブルを追加で読み込む場合がある。
  入出力コードセットの規定値は、Makefile.in 中に記載されているため、必要な場合は変更すればよい。config.h.in に記載のないものについても、skf.h で定義されているコードセット名を直接番号で指定すれば期待した動作となる。

4.2 入力サイド
4.2.1 基本的なテーブルセットアップの流れ
  上記の通り、skf では preconvert を通過した後、入力のコードセット (i.e. in_converter 内の入り口) が決まる。これは MIME デコードでも同じで、preconvert 終了時点で確定するのは変数 in_codeset であり、以降の処理は in_codeset に従って実施される。これは out_code_table.c 中の i_codeset テーブルのエントリ番号である。
  
4.2.2 入力/標準組み込み
  charset の節で記載した iso_byte_defs エントリで管理され、定義は in_code_table.c で行われている。そこで記載したとおり、変換表の実体は所定の文字集合から Unicode コードポイントへ変換するためのテーブルである。実際のテーブルのありかは、静的なものは、X-0208 (1990)/X-0212 は uni_byte_gen.c からコンパイル時に生成される uni_table.c に、それ以外は in_code_table.c にある。動的に生成されるテーブルの実体は、dyn_table.c にあり、コンパイル時にテーブルが作成されるか、または in/out_table_defs.h というコンパイル時に生成される定義ファイルにより、in_code_table.c または out_code_table.c に組み込まれる。
  具体的には、動的読み込み有効な場合にはテーブル名が NULL として #define されたリストが生成され、無効時にはテーブルの実体が上記テーブルファイル中に展開される。
  
4.2.3 入力で使われる charset
  iso-2022 対応 charset / その他のコードセットの charset は、codeset 中の定義が、コード判定後、実際に入力ストリームを処理する前にプリセットされ，その直後にコマンドライン指定が被せられる。すなわち、iso-2022 系の文字集合では、入力ストリーム処理中の指定で上書き可能である。また、処理開始時にはシフト等は指定無き限りすべてオフである。変換中の charset 定義は in_code_table.c の g0_table_mod から g3_table_mod に格納され、その時点の GL, GR は low_table および up_table に格納されている。後者はシフト指定により書き換えられる。また、指定時に low_table などの高速化のための変数およびポインタは適宜書き換える。ここで、skf ではこの low_table/up_table 内容設定は G0, G1 を書き換えた処理部の責任である。処理自体は in_decoder.c 中の Helper 関数群 (g0table2low など) に記載されているので、必要に応じてこれらの Helper 関数の適切なものを呼べばよい。
  また、入力時に用いる charset テーブルは、上記の charset 設定後の一連の処理中に必要なものが読み込まれる。codeset で指定されていないものは、on demand ベースで読み込まれる。また、4.2.4 で記載のオーバロード機能を用いた場合には、上書きされた側のテーブルは読み込まれない。これらが読み込まれていることを前提とした処理を行ってはならない。
  中国語 GB18030、Vietnum 語 VNI, VIQR は上記にあてはまらない特殊なテーブル操作を行っている。これらについては直接コードを見ること。
  
4.2.4 charset のオーバロード
  コマンドライン指定 (--set-g0 など) により、G0,G1,G2,G3 の初期設定は上書き可能である。その際に指定可能な charset は 3.1 記載の charset 分類 (iso_byte_defs_entry 定義の) 毎に決まり、エントリ毎に各プレーンへの設定可否を示すビットマップを持っている。このビットマップで設定不可となっているものは、コマンドラインから設定しても拒否される。また、マルチバイトではなく、テーブル長が 128 エントリ超のものは、G1, G2, G3 に対する設定を許していない。これらの可否の判定は、コマンドライン解析時にパーザ中でコードセット名解析の後処理で実施される。

4.2.5 MIME 処理
  MIME、および UTF-8 などの他コードセットシステムを呼び出す処理は、流れは以下のようになる。詳細はコード参照のこと。
(1) (特に MIME では) MIME ヘッダを確認し、ヘッダの有効性と指定されたコードセットが存在するか、を確認する。
(2) OK の場合、一旦シフト状態をクリアし、現在の in_codeset を退避して指定されたコードセットを in_codeset に設定し、sOCD 検出として preconvert から skf.c の skf_in_converter まで戻る。ここで sOCD が捨てられ、再度 preconvert -> in_converter という形で変換が実行される。MIME 時は、並行して MIME デコードが行われる。
(3) 標準戻り、または MIME 末尾を検出した時点で、先ほどの退避領域から in_codeset を戻し、同じく sOCD で戻る。
上記のとおり切り替えは in_codeset 掴みで重いのと、二段での呼び出しはできない。MIME 中で MIME ヘッダの検出は抑止しているが、他コードセット呼び出しを行った場合は戻れなくなる可能性がある (毎回一旦抜けて全部巻き戻しているので、スタックを消費することはない。単に上書きで in_codeset を戻せなくなるだけである)。1.9x までのこの仕様は変更されるかもしれない。

4.3 出力サイド
4.3.1 基本的なテーブルセットアップの流れ
  出力側の文字集合はコマンドライン読み込み処理後には決まっており、所定の処理はその直後に実行される。この際に使われるパラメータは、パラメータ解析時に使われた out_code であり、それを out_code_table.c 中の skf_charset_parser() 関数に渡すことにより、内部でこの後使われる global 変数の out_codeset (これは out_code_table.c 中の i_codeset テーブルのエントリ番号である) や、出力関係のテーブルが初期設定される。また、その後の細かい初期化処理は oconv_init で行われる。

4.3.2 出力テーブル外部構造
  出力テーブルは、入力テーブルと逆の Unicode コードポイントから出力のコードセットへの変換テーブルとなる。但し、Unicode 全域から所定コードポイントは通常きわめて疎なものになるため、skf では領域毎に分割してコードセット毎に有無を切り変えて容量を節約している。現在のテーブル構成に関しては三章を参照のこと。

4.3.3 出力テーブル内部構造
  テーブル内のデータは、genoconv の出力サイド毎に処理が異なっており、大別して以下の種類がある。
  
  (1) iso-2022 系：4 面の charset および latin 系の charset を格納する。パッキング構造は以下で記載する。
  (2) raw 系：出力コードを生で格納する。
  
4.3.3.1 iso-2022 系の出力テーブル。
  JIS、EUC 系およびシフト JIS などで用いられる。具体的には定義参照。格納可能な charset は 94x94 4面まで+ 96 文字文字集合一面であり、unsigned short に以下のパッキング方式を用いて格納している。
  
  (0) 各複数バイト系 charset は 0x21-0x7f に正規化され、第一文字を上位 8bit に、第二文字を下位 8bit に置く。ascii は GL に、96 文字文字集合は GR に配置し、そのまま格納する。
  (1) 複数バイト文字集合の4面は以下のようにパッキングする。
    i) bit15 = 0, bit8 = 0	第一面
    ii) bit15 = 1, bit8 = 1	第二面
    iii) bit15 = 1, bit8 = 0	第三面
    iv) bit15 = 0, bit8 = 1	第四面 (現在未使用)

  複数バイト文字集合が定義されている場合と、無い場合の面と g0def - g3def との対応は以下のようになる。g0def, g0adef, g1def は使い方が決まっている。下記参照。g2def, g3def  には，複数バイト文字集合と 1 バイト文字集合のどちらでも定義可能である。
  
  (0) 複数バイトが定義されていない場合
  　テーブルの上位 8bit は 0x00 となる。この場合は、GL (G1) が g0def，GR(G1) が g1def とする。ogldef は使わない。cns11643 は G4 を使わず、内部で特別扱いしている。以下の挙動は、skf-1.95 およびそれ以前では変更できない。
  
  (1) 複数バイトが定義されている場合
  　(i) g0adef が定義されていない場合
       順に、iso-2022 の　GL(G1) 面は g0def が対応する。GR(G2) 面は g1def を用いて、上記のパッキングされた第一面が対応する。この場合、g1def には複数バイト文字集合を定義しなければならない。第二面、第三面は G3, G4 面に対応し，コードセット定義の g2def から g3def に従って、出力が行われる。EUC 系のコードセットは、この構造を用いる。
	  (ii) g0adef が定義されている場合
       iso-2022 の G0 面を差し替えて用いる場合である。iso-2022 の　GL(G1) 面は g0def が対応し，1バイト文字集合を定義する。切り替える面は g0adef を用いて、上記のパッキングされた第一面が対応する。g0adef 面は複数バイト文字集合でなければならない。g1 面には、GR (G2) に対応する文字集合を定義する。この場合はここは 1バイト文字集合でなければならない。第二面、第三面は G3, G4 面に対応し，コードセット定義の g2def から g3def に従って、出力が行われる。

4.3.3.2 RAW 系のコードセット
  コードセット毎に処理が異なる。genoconv および oconv の BG 関係の処理参照のこと。 

4.3.3.3 Unicode 系のコードセット
  Unicode および透過指定の場合には、出力定義として charset は指定しない。B-Right/V では各面定義があるが、現在未使用。後者については brgtconv ソース参照のこと。

4.3.4 出力コードセットの扱い
  出力で使われるコードセットに伴うテーブルの設定および読み込みは、preconvert の前に行われる。必要な出力のアナウンス/BOM 出力はこの時点で行われるため、入力の読み込みの可否には依存しない。また、出力の初期値は、GL に ASCII 指定と見なし、EOF 前に GL に ASCII を戻して終了する。また、この時点で出力に指定した codeset の指定言語を弱言語としてセットする。

