この記事は、全面的に書き換えました(2019年8月原著者)。
「COBOL address」というキーワードで何回も検索されていたので目にとまったものです。プログラム中で定義したデータエリアの場所、パラメーターで渡す値を、メモリー上の格納エリアの場所で示したい、ということでしょうか。言い換えればCOBOLでポインターを扱うにはどうすればいいのか?ということになるのでしょうか。
COBOL2002
COBOL2002という規格では、新たにポインター項目とアドレス付けの機能が追加されたようです。これによってCOBOLプログラムでも、ポインターを取り扱うことができるようになるようです。COBOLなのにCのようなパラメーターの受け渡しができるようになるみたいですが、目的はC言語プログラムなどとの連携を容易にするためでしょう。詳細は「COBOL Consortium」の「第4次COBOL規格 COBOL2002のご紹介:ポインタ項目とアドレス付け機能」を参照してみて下さい。メインフレームでも各社のCOBOLコンパイラーがサポートしています。
IBMのEnterprise COBOL for z/OSによるアドレス操作例
COBOLでアドレス(ポインター)を直接扱う例として、プログラムを実行しているジョブのジョブ名を求める処理を書いてみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- IDENTIFICATION DIVISION. PROGRAM-ID. GETJOBNM. * ENVIRONMENT DIVISION. CONFIGURATION SECTION. INPUT-OUTPUT SECTION. * DATA DIVISION. WORKING-STORAGE SECTION. 01 ZOS-ASCB-PTR-L1. 03 ZOS-ASCB-PTR POINTER. 77 OUR-JOBNAME PIC X(8). LINKAGE SECTION. 01 ZOS-ASCB-ADDR POINTER. 01 ZOS-ASCB. 03 FILLER PIC X(172). 03 ASCBJBNI POINTER. 77 ZOS-CHNAME PIC X(8). * PROCEDURE DIVISION. MOVE X'00000224' TO ZOS-ASCB-PTR-L1. ① SET ADDRESS OF ZOS-ASCB-ADDR TO ZOS-ASCB-PTR. ② SET ADDRESS OF ZOS-ASCB TO ZOS-ASCB-ADDR. ③ SET ADDRESS OF ZOS-CHNAME TO ASCBJBNI. ④ DISPLAY ZOS-CHNAME. MOVE ZOS-CHNAME TO OUR-JOBNAME. ⑤ STOP RUN. * END PROGRAM GETJOBNM. ----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- |
①このプログラムを実行しているアドレス空間(ジョブ)のASCBアドレスが格納されている、ポインター・フィールド(PSAAOLD)のアドレスを、プログラム内のポインター領域ZOS-ASCB-PTRに設定する。
②プログラム内のポインター領域ZOS-ASCB-PTRが示すアドレス(x224番地)を、連係セクション領域ZOS-ASCB-ADDRとして設定します。これによって、z/OSのPSAAOLDフィールドを、変数名ZOS-ASCB-ADDRとして参照できます。
③連係セクション領域ZOS-ASCB-ADDRが示すアドレス(ASCBアドレス)を、連係セクション領域ZOS-ASCBとして設定します。これによって、z/OSのASCB領域を、変数名ZOS-ASCBとして参照できます。
④連係セクション領域ZOS-ASCB内のASCBJBNI項目が示すアドレス(CHNAMEフィールドのアドレス)を、連係セクション領域ZOS-CHNAMEとして設定します。これによって、z/OSのCHNAMEフィールドを、変数名ZOS-CHNAMEとして参照できます。z/OSのCHNAMEフィールド(CSCX領域内のフィールド)にはバッチ・ジョブのジョブ名が格納されています。
⑤連係セクション領域ZOS-CHNAMEが示す内容(CHNAMEフィールドの内容=ジョブ名)を、プログラム内領域OUR-JOBNAMEにコピーしています。単にジョブ名がわかればよいのなら、この処理は不要です。わざわざ自分のプログラム内領域に移す必要はないでしょう。
アドレス・ポインターの処理なので、プログラム内に直接データ領域として定義できないz/OSのコントロール・ブロックを、COBOLから参照するサンプルとして紹介しました。
LINKAGEセクションは、プログラム間での共用領域などを参照する際にも利用されますが、このようにz/OSや他のサブシステムの領域を参照する際にも利用できます。
DISPLAY ZOS-ASCB-ADDR.
DISPLAY ASCBJBNI.
DISPLAY ZOS-CHNAME.
DISPLAY OUR-JOBNAME.
0000655360 <--- ZOS-ASCB-ADDR
2135278592 <--- ASCBJBNI
0016344832 <--- ZOS-ASCB-ADDR
0016462552 <--- ASCBJBNI
0016344832 <--- ZOS-ASCB-ADDR
0016462552 <--- ASCBJBNI
TK@JOB#C <--- ZOS-CHNAME
0016344832 <--- ZOS-ASCB-ADDR
0016462552 <--- ASCBJBNI
TK@JOB#C <--- ZOS-CHNAME
TK@JOB#C <--- OUR-JOBNAME
期待通りにポインター領域にアドレスが格納されたか、参照しているOSの領域内容はどうなっているか、などはDISPLAY命令でデバッグできます。領域内容は、SYSOUT DDステートメントに出力されます。アドレスなどの2進数フィールドの内容は、10進数に変換されて出力されます。
MSPとVOS3のCOBOLにも、ポインターを処理する機能はあるようです。詳細は各OSのCOBOLのマニュアルを参照して下さい。
COBOLという言語を考えた時、そもそもアドレス(ポインター)を扱うこと自体が不自然に思えますが、アセンブラーに慣れた者にとっては、逆にアドレスが扱えないことに、もどかしさを覚えます。もっともそういう場合は、アセンブラーなりCなりを使いなさいということでしょうか。アドレスとかポインターとかの概念がないから、COBOLのような言語ではプログラマーによる個人差が出にくい、ということを聞いたことがあります。それだけが理由でもないでしょうが、言語の仕様上似たようなコードになってしまう、ということかも知れません。
そうだとすれば、これは企業のシステム部門にとっては、ある意味よいことでもあります。メインフレームのように企業の基幹で使われるシステムでは、品質の良いプログラムが当然のように求められますが、品質とは必ずしもバグがない、ということだけではありません。むろん性能や使いやすさなども品質のうちでありますが、企業にとっては、誰が書いても同水準の品質を保てるということも大切です。特に、今日のように自社のソフトウェア要員を教育して訓練する、などということがめっきり減ってしまった状況では、1人のスーパースターが素晴らしいプログラムを書いても、その人がいなくなり、他に誰もそのプログラムの面倒が見られなければ、結局捨てざるをえません。今日のメインフレームにおけるアプリケーション・プログラムで、圧倒的なシェアでCOBOLが使われているのも(IBMに限って言えばPL/Iもかなり使われている)、アプリとしては最もつぶしが効く言語となっているからでしょう。アドレスを扱うことはできない、という点で考えた時、それでもCOBOLがこれだけのシェアを持って使われているのは、アドレスの取扱いは必要ない、ということの表れとも言えます。