#やりたいこと:
トランザクションレコードを利用者が指定したチェック条件でチェックし、条件にヒットしたら指定のアクションを実行し、ヒットしなかったら次のチェック条件を実行するチェックインタープリタを作る。
このチェック条件は、プログラムの外部からテキストファイルで渡すことができる。
つまり、ソースファイル内にチェック条件をIF文でハードコーディングするのではなく、テキストファイルで渡せるようにする。
世の中的には「Business Rules Management System (BRMS) 」とか言うやつ。
JBOSS Rulesとかの製品があったりする。
これをCOBOLで実現する。テストのしやすさからOpenCOBOLを使う。
この後にCOBOLならではの課題がいくつか出てくるが、それを解決しながら投稿を進めたいと思うので、投稿記事がいくつかに分かれそうな感じがしている。
#チェックインタープリタの概要図:
こんなイメージを実現しようと考えている。
#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で動的メモリ割り当てしないで可変長文字列をどうやって扱うか?
特にメインルーチンとサブルーチン間で可変長文字列をやり取りするにはどうするか?
こんな単純なことで悩まなければならない。
可変長を扱うには文字列長を何らかの形で調べる、もしくは区切り文字(デリミタ)になる文字(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).