野村 芳明(日本電気株式会社 クラウドプラットフォーム事業部)
COBOL の言語仕様は特定の文字コードに縛られずに規定されています。一方で、実際のシステムでは、OS、ファイル、データベース、他言語連携(Java 等)といった環境に応じて、文字コードへの配慮、対応が必要になります。
本稿では、COBOL における文字コードの扱い、起きやすい問題、対処方法について説明します。
COBOL の規格では、文字集合に関する概念として以下の 3つが定められています。
計算機符号化文字集合は、英数字(PIC X / USAGE DISPLAY)を扱う符号化文字集合と、各国文字(PIC N / USAGE NATIONAL)を扱う符号化文字集合の 2種類で構成されます。(後者は、第4次規格で標準化されました。)
具体的な符号化文字集合および符号化表現は、実装者定義(英数字:ASCII / 各国文字:Shift-JIS、英数字:UTF-8 / 各国文字:UTF-16、翻訳時のオプションで指定等、処理系によって自由に決めてよい)となっていますが、以下の制限があります。
すなわち、COBOL では固定長の符号化表現(多くの処理系では、英数字 1文字が 1バイト、各国文字 1文字が 2バイト)が前提となっています。そのため、可変長の符号化表現を持つ文字コードを扱う場合には、注意が必要です。特に、Unicode については規格中でも言及があり、合成文字や UTF-16 のサロゲートペアのように 2つのコードポイントからなる文字について、COBOL で操作したり認識したりする特殊な方法を提供しない旨が、明記されています。
これらの問題については、次章で説明します。
COBOL 文字レパートリは、ソースコードを記述する文字の種類を規定していて、基本文字(A〜Z、a〜z)、基本数字(0〜9)、基本特殊文字(記号)、拡張文字(利用者定義語の形成に用いるための追加の文字群)で構成されます。符号化表現に依存しない抽象的な文字集合として定めらており(例えば、「MOVE」がいかなる文字コードで記述されているかによらず、MOVE文の動作は定められています)、具体的な符号化文字集合および符号化表現は、実装者定義となっています。
項目名等の利用者定義語に日本語(例えば Shift-JIS や Unicode)を用いることができるかどうかは拡張文字の範疇であり、その範囲は処理系依存です。ソースコードの移植性を考慮する場合は、利用者定義語に基本文字、基本数字、下線、ハイフンのみを用いるよう、規格に記載があります。
なお、文字定数については、いかなる文字コードで記述されていようとも、実行時には前節の計算機符号化文字集合に従って扱われます。
符号系名による符号系は、環境部の特殊名段落で定義し、ファイル記述項の CODE-SET句で参照することができます。この指定により、READ/WRITE文等の入出力の際、外部媒体上の符号化表現と、計算機符号化文字集合の符号化表現の間で変換が行われます(定義できる、または既定義の符号系は、実装者定義のため処理系依存)。特に指定を行わなければ、文字コードを意識せずバイナリデータとしてそのまま入出力を行います。
なお、データベースとの入出力を埋め込みSQL文で行う場合は、この仕組みの範疇外となるため、データベース側で入出力に用いる文字コードの設定を行い、COBOL の計算機符号化文字集合と合わせる必要があります。
固定長の符号化表現を前提とする COBOL の計算機符号化文字集合において、注意が必要となる可変長の文字コードの具体例を説明します。
以下では、COBOL の英数字 1文字、各国文字 1文字のバイト数を、多くの処理系と同じ 1バイト、2バイトとします。
Unicode は 1つの符号化文字集合に対して符号化表現が複数存在する(コードポイント U+000000 〜 U+10FFFF の値そのもので表現するとは限らない)文字コードです。UTF-8、UTF-16 は可変長、UTF-32(コードポイントそのもの)は固定長の符号化表現ですが、Unicode には複数のコードポイントで 1文字表す仕組み(合成文字や異体字セレクタ)が存在するため、符号化表現に依らずコードポイントレベルで可変長の要素を持っています。
UTF-8 は、コードポイントの小さい文字ほど少ないバイト数となるよう変換を施した値を用いる符号化表現です。ASCII 文字の範囲では 1バイト固定であることから、COBOL の英数字の符号化表現として適しています。
コードポイント | バイト数 | 主な対象 |
---|---|---|
U+000000 〜 U+00007F | 1 | ASCII 文字 |
U+000080 〜 U+0007FF | 2 | |
U+000800 〜 U+00FFFF | 3 | 多くの日本語 |
U+010000 〜 U+10FFFF | 4 | 一部の日本語 |
ただし、英数字項目に日本語等を格納する場合は、以下のように 1文字が複数桁に分かれて格納されます。
01 DATA1 PIC X(9) VALUE 'あいう'.
あ | い | う | ||||||
---|---|---|---|---|---|---|---|---|
E3 | 81 | 82 | E3 | 81 | 84 | E3 | 81 | 86 |
この場合、「E3」「81」「82」を「あ」を構成する一連のコードとして認識する方法を標準では提供しないため、それぞれ独立の文字として扱われます。(例えば部分参照で「2文字目」を参照すると「い」ではなく「81」が参照されます。)従って、項目サイズ、部分参照、INSPECT文などの文字数を意識する箇所は、独自の作り込みまたは処理系で提供されている組込関数等へ置き換えるなど、プログラムの修正が必要になる場合があります。
UTF-16 は、2バイトで表せる範囲までを 2バイトのコードポイントそのもので表し、2バイトで表せる範囲を超えるそれ以降の文字を、サロゲート領域と呼ばれるコード領域(2バイトで表せる範囲にあり、それ単体には対応する文字はないこの用途専用のコード領域)から選んだ 2つのコードポイントの組(計 4バイト)で表す符号化表現です。JIS2004 で追加された漢字を除く日本語範囲では 2バイト固定であることから、COBOL の各国文字の符号化表現として適しています。
コードポイント | バイト数 | 主な対象 |
---|---|---|
U+000000 〜 U+00FFFF | 2 | ASCII 文字、多くの日本語 |
U+010000 〜 U+10FFFF | 4 | 一部の日本語 |
ただし、JIS2004 で追加された漢字の一部はサロゲートペアを用いる必要があり、以下のように 1文字が複数桁に分かれて格納されます。
01 DATA2 PIC N(2) VALUE N'𠀋'
𠀋 | |
---|---|
D840 | DC0B |
この場合、「D840」「DC0B」を「𠀋」を構成する一連のコードとして認識する方法を標準では提供しないため、それぞれ独立の文字として扱われます。(例えば部分参照で「1文字目」を参照すると「D840」だけが参照されます。)従って、項目サイズ、部分参照、INSPECT文などの文字数を意識する箇所は、独自の作り込みまたは処理系で提供されている組込関数等へ置き換えるなど、プログラムの修正が必要になる場合があります。
なお、Java の char型は 2バイトであり、文字は UTF-16 で扱われています。Java においても、1つの char型データには、サロゲートペアの前半と後半は独立に格納されます。例えば String#length や String#charAt では COBOL と同様にサロゲートペアを意識しない文字数が用いられますが、Java ではサロゲートペアを考慮する String#codePointCount や String#codePointAt も提供されています。COBOL では相当するものが標準では提供されないため、独自の作り込みまたは処理系で提供されている組込関数等が必要になりますが、サロゲートペアを考慮していなかった処理に対して考慮する処理へのプログラム修正が必要なのは、Java でも同様です。
メインフレームやオフコンで用いられた JISコードに類する各社の文字コードでは、1バイト文字と 2バイト文字の区切りを示す漢字シフトコードによって、両者を区別しています。
COBOL の規格では、英数字項目の内容が英数字と各国文字の混在した内容になることを実装者は認めてもよく、その場合の一般規則は実装者が規定する旨が、第4次規格から追加されています。混在した内容は、以下のように漢字シフトコードも桁数を占め、2バイト文字は 1文字が複数桁に分かれて格納されます。
01 DATA3 PIC X(18) VALUE 'ABCあいうDEF'.
A | B | C | KI | あ | い | う | KO | D | E | F | |||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
41 | 42 | 43 | 1B | 24 | 40 | 24 | 22 | 24 | 24 | 24 | 26 | 1B | 28 | 4A | 44 | 45 | 46 |
この場合、漢字シフトコードを識別し、2バイト文字を構成する一連のコードを認識する方法を、標準では提供しないため、それぞれ独立の文字として扱われます。(例えば部分参照で「4文字目」を参照すると「あ」ではなく「1B」が参照されます。)従って、項目サイズ、部分参照、INSPECT文などの文字数を意識する箇所は、独自の作り込みまたは処理系で提供されている組込関数等へ置き換えるなど、プログラムの修正が必要になる場合があります。
COBOL の規格では、文字集合に関する概念として、翻訳時や実行時に用いる計算機符号化文字集合、ソースコードの記述に用いるCOBOL 文字レパートリ、外部媒体上の文字コードを指定する符号系を定めています。具体的な文字コードは実装者定義であるため、処理系ごとの対応範囲を踏まえ設計を行う必要があります。
中でも、計算機符号化文字集合は固定長の文字コードを前提としており、Unicode や JISコードのような可変長の文字コードを扱う場合は、1文字が複数桁に分かれて格納されたり、漢字シフトコードも桁数を占めて格納されます。扱うデータ範囲に該当する内容(UTF-8 の ASCII文字以外、UTF-16 のサロゲートペア、JISコードの英数字と各国文字の混在)を含むことがあるか、文字数を意識する処理を行っているか等、影響を確認し、対応する必要があります。