LoginSignup
1
0

More than 5 years have passed since last update.

COBOLでインタープリタ的なものを作るには?

Last updated at Posted at 2015-04-25

やりたいこと:

トランザクションレコードを利用者が指定したチェック条件でチェックし、条件にヒットしたら指定のアクションを実行し、ヒットしなかったら次のチェック条件を実行するチェックインタープリタを作る。

このチェック条件は、プログラムの外部からテキストファイルで渡すことができる。
つまり、ソースファイル内にチェック条件をIF文でハードコーディングするのではなく、テキストファイルで渡せるようにする。

世の中的には「Business Rules Management System (BRMS) 」とか言うやつ。
JBOSS Rulesとかの製品があったりする。

これをCOBOLで実現する。テストのしやすさからOpenCOBOLを使う。
この後にCOBOLならではの課題がいくつか出てくるが、それを解決しながら投稿を進めたいと思うので、投稿記事がいくつかに分かれそうな感じがしている。

チェックインタープリタの概要図:

こんなイメージを実現しようと考えている。
インタープリタ.jpg

GitHub上のチェックインタープリタCOBOLソース

チェックインタープリタCOBOLプロジェクト
test-main.xmlをantで「create_exe」すると、「TEST-MAIN.exe」ができます。
test-main.xmlをantで「exec」すると、チェック条件ファイルを読み込んでチェックを実行します。

課題整理:

1.データタイプは何を使うか?→文字、数値の両方が使えるXタイプを使う。
2.できるだけ汎用的なCOBOLでコードを書きたいので動的メモリ割り当てはしないこととするが、その場合、可変長文字列の取り扱いや、スタックなどをどうするか?→GitHubのチェックインタープリタCOBOLプロジェクト参照。
3.字句解析や構文解析どうするか?→字句解析、構文解析は難しいので対象外とする。それは別途行われ、仮想的なマシンのコード(アセンブラ風なやつ)をテキストファイルに出力されていて、それを実行するインタープリタを作るイメージ。
4.変数と定数のメモリ割り当てをどうするか?→後続の記事参照。
5.課題が増え次第順次追加し、別記事で投稿していきます。

課題の解決:

COBOLで動的メモリ割り当てしないで可変長文字列をどうやって扱うか?

特にメインルーチンとサブルーチン間で可変長文字列をやり取りするにはどうするか?
こんな単純なことで悩まなければならない。

IMG_20150419_0002_NEW.jpg

可変長を扱うには文字列長を何らかの形で調べる、もしくは区切り文字(デリミタ)になる文字(HIGH-VALUE等)を決めておいて、そこまで読むというような仕組みが必要。

COBOLで指定した開始桁位置から指定桁数分の文字列を切り出すコード断片:
例:変数Aで5桁目から3桁切り出す。変数名の後にカッコ開始桁位置と桁数を書く。
DISPLAY 変数A(5 : 3)

メインルーチンとサブルーチン間で可変長文字列をやり取りする:
今度はメインルーチンとサブルーチンで可変長文字列をどうやって授受するか?であるが、結局COBOLではやり方がわからなかった。

とはいえ、サブルーチン側をできるだけ汎用的な作りにしたかったので、メインルーチン側でメモリ領域を固定長で十分に確保し、サブルーチン側ではそのアドレスを参照するようなイメージで対応する。

で、ちょっとトリッキーなコードの書き方をする。
メインルーチン側のWORKING STRAGE SECTIONで、可変長文字列の授受に必要な領域を十分確保し、サブルーチン側のLINKAGE SECTIONでは、X(1)しか定義しない。
つまりサブルーチン側が短い。

サブルーチン側が短いので、index out of boundsや記憶保護違反が起きそうなコードの書き方。
ただ、メインルーチン側で十分に領域を確保しているなら問題ないはず。

OpenCobol1.1で試しているが、”-debug”オプション付きでcobcすると、実行時にout of boundsで異常終了します。OpenCobolで試すときは、”-debug”オプションはつけてはダメ。

コード断片:
メインルーチン側:

000050 WORKING-STORAGE SECTION.
000100*--------------------------------------------------------------
000110*-可変長文字列長さ
000120*--------------------------------------------------------------
000130 01 PMYMEM-PRM SYNC.
000140 03 PMYMEM-VLL PIC 9(5).
000150*--------------------------------------------------------------
000160*-可変長文字列授受エリア
000170*--------------------------------------------------------------
000180 01 PMYMEM-VAL SYNC.
000190 03 FILLER PIC X(100).

サブルーチン側:

000050 LINKAGE SECTION.
000100*--------------------------------------------------------------
000110*-可変長文字列長さ
000120*--------------------------------------------------------------
000130 01 PMYMEM-PRM SYNC.
000140 03 PMYMEM-VLL PIC 9(5).
000150*--------------------------------------------------------------
000160*-可変長文字列授受エリア
000170*--------------------------------------------------------------
000180 01 PMYMEM-VAL SYNC.
000190 03 FILLER PIC X(1).

サブルーチン側の処理:
LINKAGE SECTIONで受けた値をDISPLAY
001280 DISPLAY PMYMEM-VAL(1:PMYMEM-VLL).

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0