トップ «前の日(05-19) 最新 次の日(05-21)» 追記

Masa's blog

検索キーワード:

2009年05月20日 open-cobol(1.0)儂(わし)的解釈によるメモ

_ open-cobol(1.0)儂(わし)的解釈によるメモ

さて、私自身COBOLと付き合い出して20年以上になるわけだが(あっ、メインフレームのね)、正直、以下のサンプルで使ってる程度の命令、構文が理解できてればバッチ処理に関しては(たぶん)充分。ただし、実際に業務システムを構築する際には、JCL(Job Control Language)やユーティリティ類との組合せで力を発揮するものなので、LinuxCygwin上でのopen-cobolではCOBOLの良さが見えにくいかもしれない。

ちなみにデータベース、オンライン処理(DB/DC)に関してはメーカー(処理系)依存が大きいもんなので、一般論で語るのは何かと難しい。

インストール

Berkeley DB(4.7)
  • tar xvzf db-4.7.25.tar.gz
  • cd db-4.7.25/build_unix
  • ../dist/configure
  • make
  • make install
  • vi /etc/ld.so.conf
/usr/local/BerkeleyDB.4.7/lib
  • ldconfig
open-cobol(1.0)
  • tar xvzf open-cobol-1.0.tar.gz
  • cd open-cobol-1.0
  • CPPFLAGS=-I/usr/local/BerkeleyDB.4.7/include LDFLAGS=-L/usr/local/BerkeleyDB.4.7/lib ./configure
  • make
  • make install

サンプルプログラム

      *00111111111122222222223333333333444444444455555555556666666666777
      *89012345678901234567890123456789012345678901234567890123456789012
      *
      * open-cobol sample by m-ito@myh.no-ip.org in 2009.05.20
      *
      *  Compile : cobc -x sample.cob
      *  Run : LS=ls.dat IDX=idx.dat REL=rel.dat ./sample
      *
      * ==================================================
      * 見出し部
      * ==================================================
       IDENTIFICATION DIVISION.
       PROGRAM-ID. SAMPLE.
       AUTHOR.     M-ITO.
      * ==================================================
      * 環境部
      * ==================================================
       ENVIRONMENT DIVISION.
      * --------------------------------------------------
      * 入出力節
      * --------------------------------------------------
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
      *
      * LINE SEQENTIOAL(テキストファイル形式)
      *
           SELECT LS-FILE ASSIGN "LS"
               ORGANIZATION LINE SEQUENTIAL
               STATUS LS-STS.

ASSIGN "LS"の場合、実際に割り当てられるファイルは環境変数LSから取得される(open-cobol独自仕様?)。

ORGANIZATION LINE SEQUENTIALは、いわゆるテキストファイル(エディタで作れるやつ)を順編成ファイルとして扱うことが出来るので、UNIXWindows環境では便利。

ORGANIZATION SEQUENTIALは、本来の(メインフレーム上での)順編成ファイルを扱う場合。

      *
      * INDEX(索引順編成形式)
      *
           SELECT IDX-FILE ASSIGN "IDX"
               ORGANIZATION INDEXED
               ACCESS DYNAMIC
               RECORD KEY IDX-KEY
               ALTERNATE RECORD KEY IS IDX-KEY2 WITH DUPLICATES
               STATUS IDX-STS.

索引順編成ファイルBerkeley DBを利用して実装されている。ちょっとしたデータ管理ならデータベースが無くてもこれで充分かもしれない。(トランザクションロールバックが使えれば本当にデータベースは必要無いかも)

      *
      * RELATIVE(相対編成形式)
      *
           SELECT REL-FILE ASSIGN "REL"
               ORGANIZATION RELATIVE
               ACCESS DYNAMIC
               RELATIVE KEY REL-KEY
               STATUS REL-STS.

相対編成ファイルも一時期ある顧客のシステムでよく使った。ようは、件数を指定して直接その件数目にアクセスできる形式。

      * ==================================================
      * データ部
      * ==================================================
       DATA DIVISION.
      * --------------------------------------------------
      * ファイル節
      * --------------------------------------------------
       FILE SECTION.
      *
      * LINE SEQENTIOAL(テキストファイル形式)
      *
       FD LS-FILE.
       01 LS-REC.
          02 LS-SEQ PIC S9(3)
             SIGN IS LEADING
             SEPARATE CHARACTER.
          02 LS-DATA PIC X(80).

SIGN IS LEADINGSEPARATE CHARACTERUNIX, Windows環境で、数値データをASCIIフラットファイルに格納して扱う(UNIXという考え方 定理5)のに非常に適している。S9(3)の場合は"-999" 〜 "+999"の4byteの文字列として格納される。

      *
      * INDEX(索引順編成形式)
      *
       FD IDX-FILE.
       01 IDX-REC.
          02 IDX-KEY PIC S9(3)
             SIGN IS LEADING
             SEPARATE CHARACTER.
          02 IDX-DATA.
             03  IDX-KEY2  PIC X(10).
             03  FILLER    PIC X(70).
      *
      * RELATIVE(相対編成形式)
      *
       FD REL-FILE.
       01 REL-REC.
          02 REL-SEQ PIC S9(3)
             SIGN IS LEADING
             SEPARATE CHARACTER.
          02 REL-DATA PIC X(80).
      * --------------------------------------------------
      * 作業領域節
      * --------------------------------------------------
       WORKING-STORAGE SECTION.

WORKING-STORAGE SECTIONでは変数の定義を行う。常に批判の的になる事だが、基本的にCOBOLで扱う変数は全て大局(グローバル)変数なのだ。

  • X(10) 10バイトの文字列
  • 9(10) 10桁の正整数
  • S9(10) 10桁の整数
  • S9(10)V9(5) 15桁(小数点以下5桁)の実数
  • N(10) 日本語10桁の文字列
       01  LS-STS    PIC X(2).
       01  IDX-STS   PIC X(2).
       01  REL-STS   PIC X(2).
      *
       01  END-SW    PIC X(3) VALUE "OFF".
       01  INV-SW    PIC X(3) VALUE "OFF".

VALUE句で初期値を指定する。

       01  REL-KEY   PIC 9(3).
       01  WK-SEQ    PIC S9(3).
       01  I         PIC 9(3).
       01  J         PIC 9(3).
      *
       01  WK-UNSTRING PIC X(80).
       01  WK-UNSTRING-1 PIC X(10).
       01  WK-UNSTRING-2 PIC X(10).
       01  WK-UNSTRING-3 PIC X(10).
       01  WK-UNSTRING-4 PIC X(10).
      *
       01  WK-INSPECT PIC X(80).
       01  WK-INSPECT-CNT PIC 9(3).
      *
       01  WK-EDIT-1      PIC ---,---,---9.
       01  WK-EDIT-2      PIC ZZZ,ZZZ,ZZZ9.
      *
       01  WK-COMPUTE     PIC S9(10)V9(10).
       01  WK-COMPUTE-2   PIC ---,---,---9.9(10).

数値項目を簡単に文書的に見やすく編集する機能があるのがCOBOLの良い所。

      *
       01  WK-DIVIDE-SHO  PIC S9(10).
       01  WK-DIVIDE-AMARI  PIC S9(10).
      *
       01  WK-VALUEHEX    PIC X(4) VALUE X"B4C1BBFA".

16進の定数は X"16進数表現" で表す。

      *
       01  WK-VALUEKANJI  PIC N(2) VALUE "漢字".
      *
       01  WK-ACCEPT      PIC X(80).
      *
       01  WK-REDEFINES   PIC X(7).
       01  WK-REDEFINES-R REDEFINES WK-REDEFINES.
           02  WK-REDEFINES-G PIC X(1).
           02  WK-REDEFINES-NN PIC X(2).
           02  WK-REDEFINES-TT PIC X(2).
           02  WK-REDEFINES-HH PIC X(2).

REDEFINES句COBOLに特徴的な機能。異なる変数を同じ領域に重ね合わせるイメージ。他の言語ならポインターを使うような場面かと思うが、この使い勝手はCOBOLに独特な物で、他の言語では味わえない。

      *
       01  WK-OCCURS.
           02  FILLER OCCURS 12.
               03  WK-OCCURS-X     PIC X(1).
       01  WK-OCCURS2.
           02  FILLER OCCURS 3.
               03  FILLER OCCURS 4.
                   04  WK-OCCURS2-X PIC X(1).

配列はOCCURS句で指定する。多次元配列もできる。

      *
       01  WK-SEARCH-TABLE-R.
           02  FILLER PIC X(16) VALUE "000001YAGI".
           02  FILLER PIC X(16) VALUE "000002NAKAKOJI".
           02  FILLER PIC X(16) VALUE "000003WATANABE".
           02  FILLER PIC X(16) VALUE "000004WAKIYAMA".
           02  FILLER PIC X(16) VALUE "000005MIYOSHI".
           02  FILLER PIC X(16) VALUE "000006KOBAYASHI".
           02  FILLER PIC X(16) VALUE "000007MATSUI".
           02  FILLER PIC X(16) VALUE "000008HOSONO".
           02  FILLER PIC X(16) VALUE "000009NAKAMURA".
           02  FILLER PIC X(16) VALUE "000010ITO".
       01  WK-SEARCH-TABLE REDEFINES WK-SEARCH-TABLE-R.
           02  WK-SEARCH OCCURS 10 ASCENDING KEY WK-SEARCH-KEY
                                   INDEXED BY WK-SEARCH-IDX.
               03  WK-SEARCH-KEY      PIC X(6).
               03  WK-SEARCH-NAME     PIC X(10).
       01  WK-SEARCH-FIND-SW    PIC X(3).

テーブルワークエリアに対しての2分木サーチに言語レベルで対応している。

      *
       01  WK-FUNCTION-DATE PIC X(80).
      *
       01  WK-INITIALIZE.
           02  FILLER           PIC X(7) VALUE "XXXXXXX".
           02  FILLER           PIC 9(7) VALUE 9999999.
           02  WK-INITIALIZE-X  PIC X(7) VALUE "XXXXXXX".
           02  WK-INITIALIZE-9  PIC 9(7) VALUE 9999999.
      * ==================================================
      * 手続き部
      * ==================================================
       PROCEDURE DIVISION.
      * --------------------------------------------------
      * 主処理
      * --------------------------------------------------
        MAIN-EN.
      *
      * 順編成ファイルテスト
           PERFORM SUB-LS-FILE-TEST-EN THRU SUB-LS-FILE-TEST-EX.

サブルーチン呼び出しはPERFORM文で行う。

      *
      * 索引順編成ファイルテスト
           PERFORM SUB-IDX-FILE-TEST-EN THRU SUB-IDX-FILE-TEST-EX.
      *
      * 相対編成ファイルテスト
           PERFORM SUB-REL-FILE-TEST-EN THRU SUB-REL-FILE-TEST-EX.
      *
      * IF文テスト
           PERFORM SUB-IF-TEST-EN THRU SUB-IF-TEST-EX.
      *
      * EVALUATE文テスト
           PERFORM SUB-EVALUATE-TEST-EN THRU SUB-EVALUATE-TEST-EX.
      *
      * PERFORM文テスト
           PERFORM SUB-PERFORM-TEST-EN THRU SUB-PERFORM-TEST-EX.
      *
      * UNSTRING文テスト
           PERFORM SUB-UNSTRING-TEST-EN THRU SUB-UNSTRING-TEST-EX.
      *
      * INSPECT文テスト
           PERFORM SUB-INSPECT-TEST-EN THRU SUB-INSPECT-TEST-EX.
      *
      * 編集テスト
           PERFORM SUB-EDIT-TEST-EN THRU SUB-EDIT-TEST-EX.
      *
      * COMPUTE文テスト
           PERFORM SUB-COMPUTE-TEST-EN THRU SUB-COMPUTE-TEST-EX.
      *
      * DIVIDE文テスト
           PERFORM SUB-DIVIDE-TEST-EN THRU SUB-DIVIDE-TEST-EX.
      *
      * VALUE(HEX)文テスト
           PERFORM SUB-VALUEHEX-TEST-EN THRU SUB-VALUEHEX-TEST-EX.
      *
      * VALUE(漢字)文テスト
           PERFORM SUB-VALUEKANJI-TEST-EN THRU SUB-VALUEKANJI-TEST-EX.
      *
      * ACCEPT文テスト
           PERFORM SUB-ACCEPT-TEST-EN THRU SUB-ACCEPT-TEST-EX.
      *
      * REDEFINES文テスト
           PERFORM SUB-REDEFINES-TEST-EN THRU SUB-REDEFINES-TEST-EX.
      *
      * OCCURS文テスト
           PERFORM SUB-OCCURS-TEST-EN THRU SUB-OCCURS-TEST-EX.
      *
      * SEARCH文テスト
           PERFORM SUB-SEARCH-TEST-EN THRU SUB-SEARCH-TEST-EX.
      *
      * FUNCTION-DATE文テスト
           PERFORM SUB-DATE-TEST-EN THRU SUB-DATE-TEST-EX.
      *
      * INITIALIZE文テスト
           PERFORM SUB-INITIALIZE-TEST-EN THRU SUB-INITIALIZE-TEST-EX.
      *
        MAIN-EX.
           MOVE ZERO TO RETURN-CODE.
           GOBACK.

プログラムの終了には上記のGOBACK以外にSTOP RUNもよく使われる。

      * --------------------------------------------------
      * 順編成ファイルテスト
      * --------------------------------------------------
       SUB-LS-FILE-TEST-EN.
           DISPLAY "== SUB-LS-FILE-TEST-EN =="
      *
      * LS-FILEにテストデータ出力
      *
           MOVE -5 TO WK-SEQ.

ワークへの代入はMOVE文で行う。

           OPEN OUTPUT LS-FILE.

ファイルのアクセスに先だってOPEN文によるオープン処理(そのままやがな)が必要。

      *
           ADD 1 TO WK-SEQ.

計算命令はCOMPUTE文というのが有って、通常の計算式はそちらを使う事が多いけれど、単純に1インクリメントする場合はADD文を使う事が多い(気分的なもの)。wk-seq = wk-seq + 1とwk-seq++の違いみたいな物。

           MOVE WK-SEQ TO LS-SEQ.
           MOVE "LINE 1" TO LS-DATA.
           WRITE LS-REC.

ファイルへの書き出しはWRITE文で行う。書き出しの単位は常にレコード単位となる。

      *
           ADD 1 TO WK-SEQ.
           MOVE WK-SEQ TO LS-SEQ.
           MOVE "LINE 2" TO LS-DATA.
           WRITE LS-REC.
      *
           ADD 1 TO WK-SEQ.
           MOVE WK-SEQ TO LS-SEQ.
           MOVE "LINE 3" TO LS-DATA.
           WRITE LS-REC.
      *
           ADD 1 TO WK-SEQ.
           MOVE WK-SEQ TO LS-SEQ.
           MOVE "LINE 4" TO LS-DATA.
           WRITE LS-REC.
      *
           ADD 1 TO WK-SEQ.
           MOVE WK-SEQ TO LS-SEQ.
           MOVE "LINE 5" TO LS-DATA.
           WRITE LS-REC.
      *
           ADD 1 TO WK-SEQ.
           MOVE WK-SEQ TO LS-SEQ.
           MOVE "LINE 6" TO LS-DATA.
           WRITE LS-REC.
      *
           ADD 1 TO WK-SEQ.
           MOVE WK-SEQ TO LS-SEQ.
           MOVE "LINE 7" TO LS-DATA.
           WRITE LS-REC.
      *
           ADD 1 TO WK-SEQ.
           MOVE WK-SEQ TO LS-SEQ.
           MOVE "LINE 8" TO LS-DATA.
           WRITE LS-REC.
      *
           ADD 1 TO WK-SEQ.
           MOVE WK-SEQ TO LS-SEQ.
           MOVE "LINE 9" TO LS-DATA.
           WRITE LS-REC.
      *
           ADD 1 TO WK-SEQ.
           MOVE WK-SEQ TO LS-SEQ.
           MOVE "LINE 10" TO LS-DATA.
           WRITE LS-REC.
      *
           CLOSE LS-FILE.

ファイルを使い終ったらCLOSE文でクローズ処理(これまたそのまま...)を行う。バッファーと物理ディスクとの同期が行われる(たぶん)。

      *
      * LS-FILE 読み込み
      *
           OPEN INPUT LS-FILE.
      *
           MOVE "OFF" TO END-SW.
           READ LS-FILE AT END
               MOVE "ON" TO END-SW
           END-READ.

順編成ファイルの読み込みはREAD AT END文を使う。

           PERFORM UNTIL (END-SW = "ON")

条件指定の繰り返しにはPERFORM UNTIL文を使う。他の言語と違って繰り返しを抜ける条件を指定する点に注意。

               DISPLAY "LS-FILE : " LS-REC

メッセージの出力にはDISPLAY文を使う。メインフレームの場合はUPON ほにゃららで出力先を指定できたが、open-cobolの場合にどんな出力先指定が出来るかは未調査。

               READ LS-FILE AT END
                   MOVE "ON" TO END-SW
               END-READ
           END-PERFORM.
      *
           CLOSE LS-FILE.
      *
           DISPLAY "== SUB-LS-FILE-TEST-EX ==".
       SUB-LS-FILE-TEST-EX.
           EXIT.

サーブルーチンの最後はEXIT文で閉める。

      * --------------------------------------------------
      * 索引順編成ファイルテスト
      * --------------------------------------------------
       SUB-IDX-FILE-TEST-EN.
           DISPLAY "== SUB-IDX-FILE-TEST-EN =="
      *
      * IDX-FILEにテストデータ出力
      *
           OPEN INPUT LS-FILE.
           OPEN OUTPUT IDX-FILE.
      *
           MOVE "OFF" TO END-SW.
           READ LS-FILE AT END
               MOVE "ON" TO END-SW
           END-READ.
           PERFORM UNTIL (END-SW = "ON")
               MOVE LS-REC TO IDX-REC
               WRITE IDX-REC
               READ LS-FILE AT END
                   MOVE "ON" TO END-SW
               END-READ
           END-PERFORM.
      *
           CLOSE LS-FILE.
           CLOSE IDX-FILE.
      *
      * IDX-FILE直読み
      *
           OPEN INPUT IDX-FILE.
      *
           MOVE 1 TO IDX-KEY.
           MOVE "OFF" TO INV-SW
           READ IDX-FILE INVALID
               MOVE "ON" TO INV-SW
           END-READ.

索引順編成ファイルを読む場合はREAD INVALID文を使う。

           DISPLAY "IDX-FILE DIRECT(IDX-KEY = " IDX-KEY ") : " IDX-REC.
      *
           CLOSE IDX-FILE.
      *
      * IDX-FILE位置指定&連続読み
      *
           OPEN INPUT IDX-FILE.
      *
           MOVE "OFF" TO END-SW
           MOVE "OFF" TO INV-SW
           MOVE 3 TO IDX-KEY.
           START IDX-FILE KEY >= IDX-KEY INVALID
               MOVE "ON" TO INV-SW
           END-START.
           READ IDX-FILE NEXT AT END
               MOVE "ON" TO END-SW
           END-READ.
           PERFORM UNTIL (END-SW = "ON")
               DISPLAY "IDX-FILE(IDX-KEY >= " IDX-KEY ") : " IDX-REC
               READ IDX-FILE NEXT AT END
                   MOVE "ON" TO END-SW
               END-READ
           END-PERFORM.

索引順編成ファイルの特定のレコードに位置付けるにはSTART INVALID文を使い、位置付けたレコードからキー順に読み込むにはREAD NEXT文を使用する。

      *
           CLOSE IDX-FILE.
      *
      * IDX-FILE ALTERNATE-KEYによる位置指定&連続読み
      *
           OPEN INPUT IDX-FILE.
      *
           MOVE "OFF" TO END-SW
           MOVE "OFF" TO INV-SW
           MOVE "LINE 3" TO IDX-KEY2.
           START IDX-FILE KEY >= IDX-KEY2 INVALID
               MOVE "ON" TO INV-SW
           END-START.
           READ IDX-FILE NEXT AT END
               MOVE "ON" TO END-SW
           END-READ.
           PERFORM UNTIL (END-SW = "ON")
               DISPLAY "IDX-FILE(IDX-KEY2 >= " IDX-KEY2 ") : " IDX-REC
               READ IDX-FILE NEXT AT END
                   MOVE "ON" TO END-SW
               END-READ
           END-PERFORM.

索引順編成ファイルの特定のレコードに位置付けるには複数のキー(ALTERNATE KEY)が利用できる。

      *
           CLOSE IDX-FILE.
      *
           DISPLAY "== SUB-IDX-FILE-TEST-EX ==".
       SUB-IDX-FILE-TEST-EX.
           EXIT.
      * --------------------------------------------------
      * 相対編成ファイルテスト
      * --------------------------------------------------
       SUB-REL-FILE-TEST-EN.
           DISPLAY "== SUB-REL-FILE-TEST-EN =="
      *
      * REL-FILEにテストデータ出力
      *
           OPEN INPUT LS-FILE.
           OPEN OUTPUT REL-FILE.
      *
           MOVE ZERO TO REL-KEY.
           MOVE "OFF" TO END-SW.
           READ LS-FILE AT END
               MOVE "ON" TO END-SW
           END-READ.
           PERFORM UNTIL (END-SW = "ON")
               MOVE LS-REC TO REL-REC
               ADD 1 TO REL-KEY
               WRITE REL-REC
               READ LS-FILE AT END
                   MOVE "ON" TO END-SW
               END-READ
           END-PERFORM.
      *
           CLOSE LS-FILE.
           CLOSE REL-FILE.
      *
      * REL-FILE読み込み
      *
           OPEN INPUT REL-FILE.
      *
           MOVE "OFF" TO INV-SW
           MOVE 6 TO REL-KEY.
           READ REL-FILE INVALID
               MOVE "ON" TO INV-SW
           END-READ.
           PERFORM UNTIL (INV-SW = "ON")
               DISPLAY "REL-FILE : " REL-REC
               ADD 1 TO REL-KEY
               READ REL-FILE INVALID
                   MOVE "ON" TO INV-SW
               END-READ
           END-PERFORM.

相対編成ファイルの読み込みにはREAD INVALID文を使用する。

      *
           CLOSE REL-FILE.
      *
           DISPLAY "== SUB-REL-FILE-TEST-EX ==".
       SUB-REL-FILE-TEST-EX.
           EXIT.
      * --------------------------------------------------
      * IF文テスト
      * --------------------------------------------------
       SUB-IF-TEST-EN.
           DISPLAY "== SUB-IF-TEST-EN =="
      *
           OPEN INPUT LS-FILE.
      *
           MOVE "OFF" TO END-SW.
           READ LS-FILE AT END
               MOVE "ON" TO END-SW
           END-READ.
           PERFORM UNTIL (END-SW = "ON")
               IF (LS-SEQ < ZERO)
                   DISPLAY "MINUS : " LS-REC
               ELSE
                   DISPLAY "PLUS : " LS-REC
               END-IF

IF文の条件式には >, >=, =, <=, <, AND, OR が使える。

               READ LS-FILE AT END
                   MOVE "ON" TO END-SW
               END-READ
           END-PERFORM.
      *
           CLOSE LS-FILE.
      *
           DISPLAY "== SUB-IF-TEST-EX ==".
       SUB-IF-TEST-EX.
           EXIT.
      * --------------------------------------------------
      * EVALUATE文テスト
      * --------------------------------------------------
       SUB-EVALUATE-TEST-EN.
           DISPLAY "== SUB-EVALUATE-TEST-EN =="
      *
           OPEN INPUT LS-FILE.
      *
           MOVE "OFF" TO END-SW.
           READ LS-FILE AT END
               MOVE "ON" TO END-SW
           END-READ.
           PERFORM UNTIL (END-SW = "ON")
               EVALUATE TRUE
               WHEN (LS-SEQ < ZERO)
                   DISPLAY "MINUS : " LS-REC
               WHEN (LS-SEQ > ZERO)
                   DISPLAY "PLUS : " LS-REC
               WHEN OTHER
                   DISPLAY "ZERO : " LS-REC
               END-EVALUATE

条件多分岐にはEVALUATE文を使う。

               READ LS-FILE AT END
                   MOVE "ON" TO END-SW
               END-READ
           END-PERFORM.
      *
           CLOSE LS-FILE.
      *
           DISPLAY "== SUB-EVALUATE-TEST-EX ==".
       SUB-EVALUATE-TEST-EX.
           EXIT.
      * --------------------------------------------------
      * PERFORM文テスト
      * --------------------------------------------------
       SUB-PERFORM-TEST-EN.
           DISPLAY "== SUB-PERFORM-TEST-EN =="
      *
           PERFORM VARYING I FROM 1 BY 3 UNTIL (I > 20)
               DISPLAY "PERFORM I = " I
           END-PERFORM.

繰り返し文の一例。変数Iの値を1から3づつ増分し、Iが20より大きくなるまで繰り返す。

      *
           DISPLAY "== SUB-PERFORM-TEST-EX ==".
       SUB-PERFORM-TEST-EX.
           EXIT.
      * --------------------------------------------------
      * UNSTRING文テスト
      * --------------------------------------------------
       SUB-UNSTRING-TEST-EN.
           DISPLAY "== SUB-UNSTRING-TEST-EN ==".
      *
           MOVE "APPLE ORANGE     LEMON           PINE" TO WK-UNSTRING.
           UNSTRING WK-UNSTRING DELIMITED BY ALL SPACE
               INTO WK-UNSTRING-1
                    WK-UNSTRING-2
                    WK-UNSTRING-3
                    WK-UNSTRING-4.
           DISPLAY "UNSTRING-1 =(" WK-UNSTRING-1 ")"
           DISPLAY "UNSTRING-2 =(" WK-UNSTRING-2 ")"
           DISPLAY "UNSTRING-3 =(" WK-UNSTRING-3 ")"
           DISPLAY "UNSTRING-4 =(" WK-UNSTRING-4 ")"
      *
           MOVE "APPLE,ORANGE,LEMON,PINE" TO WK-UNSTRING.
           UNSTRING WK-UNSTRING DELIMITED BY ","
               INTO WK-UNSTRING-1
                    WK-UNSTRING-2
                    WK-UNSTRING-3
                    WK-UNSTRING-4.
           DISPLAY "UNSTRING-1 =(" WK-UNSTRING-1 ")"
           DISPLAY "UNSTRING-2 =(" WK-UNSTRING-2 ")"
           DISPLAY "UNSTRING-3 =(" WK-UNSTRING-3 ")"
           DISPLAY "UNSTRING-4 =(" WK-UNSTRING-4 ")"

文字列の分割にはUNSTRING文を使う。メインフレームではあまり無いが、CSVファイルを扱う場合に便利。

      *
           DISPLAY "== SUB-UNSTRING-TEST-EX ==".
       SUB-UNSTRING-TEST-EX.
           EXIT.
      * --------------------------------------------------
      * INSPECT文テスト
      * --------------------------------------------------
       SUB-INSPECT-TEST-EN.
           DISPLAY "== SUB-INSPECT-TEST-EN ==".
      *
           MOVE "AAA BBB AAA CCC AAA EEE AAA" TO WK-INSPECT.
           MOVE ZERO TO WK-INSPECT-CNT.
           INSPECT WK-INSPECT TALLYING WK-INSPECT-CNT FOR ALL "AAA".
           DISPLAY "INSPECT-CNT = " WK-INSPECT-CNT.
      *
           INSPECT WK-INSPECT REPLACING ALL "AAA" BY "aaa".
           DISPLAY "WK-INSPECT(REPLACED) = " WK-INSPECT.

文字列の置換や文字列の出現回数を数えるにはINSPECT REPLACE文INSPECT TALLYING文を使う。

      *
           DISPLAY "== SUB-INSPECT-TEST-EX ==".
       SUB-INSPECT-TEST-EX.
           EXIT.
      * --------------------------------------------------
      * 編集テスト
      * --------------------------------------------------
       SUB-EDIT-TEST-EN.
           DISPLAY "== SUB-EDIT-TEST-EN ==".
      *
           MOVE 123456 TO WK-EDIT-1.
           DISPLAY "WK-EDIT-1 [123456] = " WK-EDIT-1.
           MOVE -123456 TO WK-EDIT-1.
           DISPLAY "WK-EDIT-1 [-123456] = " WK-EDIT-1.
           MOVE 123456 TO WK-EDIT-2.
           DISPLAY "WK-EDIT-2 [123456] = " WK-EDIT-2.
           MOVE -123456 TO WK-EDIT-2.
           DISPLAY "WK-EDIT-2 [-123456] = " WK-EDIT-2.

PIC句を使うと数値データを簡単に見やすい形式に編集できる。

      *
           DISPLAY "== SUB-EDIT-TEST-EX ==".
       SUB-EDIT-TEST-EX.
           EXIT.
      * --------------------------------------------------
      * COMPUTE文テスト
      * --------------------------------------------------
       SUB-COMPUTE-TEST-EN.
           DISPLAY "== SUB-COMPUTE-TEST-EN ==".
      *
           COMPUTE WK-COMPUTE = 1000 * 123 / (100 - 10 + 123).
           MOVE WK-COMPUTE TO WK-COMPUTE-2.
           DISPLAY "WK-COMPUTE = " WK-COMPUTE-2.

一般的な計算はCOMPUTE文で行う。

      *
           DISPLAY "== SUB-COMPUTE-TEST-EX ==".
       SUB-COMPUTE-TEST-EX.
           EXIT.
      * --------------------------------------------------
      * DIVIDE文テスト
      * --------------------------------------------------
       SUB-DIVIDE-TEST-EN.
           DISPLAY "== SUB-DIVIDE-TEST-EN ==".
      *
           DIVIDE 100 BY 27 GIVING WK-DIVIDE-SHO
                            REMAINDER WK-DIVIDE-AMARI.

でも割算の余りを求めたい場合にはDIVIDE文が便利。

           DISPLAY "DIVIDE 100/27 = " WK-DIVIDE-SHO
                   " ... " WK-DIVIDE-AMARI.
      *
           DISPLAY "== SUB-DIVIDE-TEST-EX ==".
       SUB-DIVIDE-TEST-EX.
           EXIT.
      * --------------------------------------------------
      * VALUE(HEX)文テスト
      * --------------------------------------------------
       SUB-VALUEHEX-TEST-EN.
           DISPLAY "== SUB-VALUEHEX-TEST-EN ==".
      *
           DISPLAY "VALUE HEX = (" WK-VALUEHEX ")".

16進数でもデータの表現ができる。

      *
           DISPLAY "== SUB-VALUEHEX-TEST-EX ==".
       SUB-VALUEHEX-TEST-EX.
           EXIT.
      * --------------------------------------------------
      * VALUE(漢字)文テスト
      * --------------------------------------------------
       SUB-VALUEKANJI-TEST-EN.
           DISPLAY "== SUB-VALUEKANJI-TEST-EN ==".
      *
           DISPLAY "VALUE KANJI = (" WK-VALUEKANJI ")".

当然漢字も扱える。ただし、メーカ依存(機種依存)あり。

      *
           DISPLAY "== SUB-VALUEKANJI-TEST-EX ==".
       SUB-VALUEKANJI-TEST-EX.
           EXIT.
      * --------------------------------------------------
      * ACCEPT文テスト
      * --------------------------------------------------
       SUB-ACCEPT-TEST-EN.
           DISPLAY "== SUB-ACCEPT-TEST-EN ==".
      *
           DISPLAY "ACCEPT FROM SYSIN(何か入力して下さい): ".
           ACCEPT WK-ACCEPT FROM SYSIN.
           DISPLAY "WK-ACCEPT SYSIN = " WK-ACCEPT.
      *
           ACCEPT WK-ACCEPT FROM DATE.
           DISPLAY "WK-ACCEPT DATE = " WK-ACCEPT.
      *
           ACCEPT WK-ACCEPT FROM TIME.
           DISPLAY "WK-ACCEPT TIME = " WK-ACCEPT.

SYSINからの入力、日付の取得、時刻の取得にはACCEPT文を利用する。

      *
           DISPLAY "== SUB-ACCEPT-TEST-EX ==".
       SUB-ACCEPT-TEST-EX.
           EXIT.
      * --------------------------------------------------
      * REDEFINES文テスト
      * --------------------------------------------------
       SUB-REDEFINES-TEST-EN.
           DISPLAY "== SUB-REDEFINES-TEST-EN ==".
      *
           MOVE "4210519" TO WK-REDEFINES.
           DISPLAY "WK-REDEFINES-G = " WK-REDEFINES-G.
           DISPLAY "WK-REDEFINES-NN = " WK-REDEFINES-NN.
           DISPLAY "WK-REDEFINES-TT = " WK-REDEFINES-TT.
           DISPLAY "WK-REDEFINES-HH = " WK-REDEFINES-HH.

データを決まったフォーマットに分割するのにREDEFINES句は便利。

      *
           DISPLAY "== SUB-REDEFINES-TEST-EX ==".
       SUB-REDEFINES-TEST-EX.
           EXIT.
      * --------------------------------------------------
      * OCCURS文テスト
      * --------------------------------------------------
       SUB-OCCURS-TEST-EN.
           DISPLAY "== SUB-OCCURS-TEST-EN ==".
      *
           MOVE "ABCDEFGHIJKL" TO WK-OCCURS.
           PERFORM VARYING I FROM 1 BY 1 UNTIL (I > 12)
               DISPLAY "WK-OCCURS-X(" I ") = " WK-OCCURS-X(I)
           END-PERFORM.
      *
           MOVE "ABCDEFGHIJKL" TO WK-OCCURS2.
           PERFORM VARYING I FROM 1 BY 1 UNTIL (I > 3)
               PERFORM VARYING J FROM 1 BY 1 UNTIL (J > 4)
                   DISPLAY "WK-OCCURS2-X(" I " " J ") = "
                           WK-OCCURS2-X(I J)
               END-PERFORM
           END-PERFORM.

配列にはOCCURS句を使用する。

      *
           DISPLAY "== SUB-OCCURS-TEST-EX ==".
       SUB-OCCURS-TEST-EX.
           EXIT.
      * --------------------------------------------------
      * SEARCH文テスト
      * --------------------------------------------------
       SUB-SEARCH-TEST-EN.
           DISPLAY "== SUB-SEARCH-TEST-EN ==".
      *
           SEARCH ALL WK-SEARCH
               AT END
                   MOVE "OFF" TO WK-SEARCH-FIND-SW
               WHEN (WK-SEARCH-KEY(WK-SEARCH-IDX) = "000005")
                   MOVE "ON" TO WK-SEARCH-FIND-SW
           END-SEARCH

ワークエリアの2分木サーチがSEARCH ALL文で出来る。

      *
           IF (WK-SEARCH-FIND-SW = "ON")
               DISPLAY "SEARCH OK KEY = " WK-SEARCH-KEY(WK-SEARCH-IDX)
               DISPLAY "SEARCH OK NAME = " WK-SEARCH-NAME(WK-SEARCH-IDX)
           ELSE
               DISPLAY "SEARCH NG"
           END-IF.
      *
           DISPLAY "== SUB-SEARCH-TEST-EX ==".
       SUB-SEARCH-TEST-EX.
           EXIT.
      * --------------------------------------------------
      * FUNCTION-DATE文テスト
      * --------------------------------------------------
       SUB-DATE-TEST-EN.
           DISPLAY "== SUB-FUNCTION-DATE-TEST-EN ==".
      *
           MOVE FUNCTION CURRENT-DATE TO WK-FUNCTION-DATE.
           DISPLAY "WK-FUNCTION-DATE = " WK-FUNCTION-DATE.

日付の年を西暦4桁で取得する場合はFUNCTION CURRENT-DATEを使う。

      *
           DISPLAY "== SUB-FUNCTION-DATE-TEST-EX ==".
       SUB-DATE-TEST-EX.
           EXIT.
      * --------------------------------------------------
      * INITIALIZE文テスト
      * --------------------------------------------------
       SUB-INITIALIZE-TEST-EN.
           DISPLAY "== SUB-INITIALIZE-TEST-EN ==".
      *
           DISPLAY "WK-INITIALIZE(BEFORE) = " WK-INITIALIZE.
           INITIALIZE WK-INITIALIZE.
           DISPLAY "WK-INITIALIZE(AFTER) = " WK-INITIALIZE.

ワークエリアの初期化にはINITIALIZE文を使う。PIC句に合わせた適切な値で初期化してくれる。

      *
           DISPLAY "== SUB-INITIALIZE-TEST-EX ==".
       SUB-INITIALIZE-TEST-EX.
           EXIT.

実行結果

== SUB-LS-FILE-TEST-EN ==
LS-FILE : -004LINE 1
LS-FILE : -003LINE 2
LS-FILE : -002LINE 3
LS-FILE : -001LINE 4
LS-FILE : +000LINE 5
LS-FILE : +001LINE 6
LS-FILE : +002LINE 7
LS-FILE : +003LINE 8
LS-FILE : +004LINE 9
LS-FILE : +005LINE 10
== SUB-LS-FILE-TEST-EX ==
== SUB-IDX-FILE-TEST-EN ==
IDX-FILE DIRECT(IDX-KEY = +001) : +001LINE 6
IDX-FILE(IDX-KEY >= +003) : +003LINE 8
IDX-FILE(IDX-KEY >= +004) : +004LINE 9
IDX-FILE(IDX-KEY >= +005) : +005LINE 10
IDX-FILE(IDX-KEY >= -001) : -001LINE 4
IDX-FILE(IDX-KEY >= -002) : -002LINE 3
IDX-FILE(IDX-KEY >= -003) : -003LINE 2
IDX-FILE(IDX-KEY >= -004) : -004LINE 1
IDX-FILE(IDX-KEY2 >= LINE 3    ) : -002LINE 3
IDX-FILE(IDX-KEY2 >= LINE 4    ) : -001LINE 4
IDX-FILE(IDX-KEY2 >= LINE 5    ) : +000LINE 5
IDX-FILE(IDX-KEY2 >= LINE 6    ) : +001LINE 6
IDX-FILE(IDX-KEY2 >= LINE 7    ) : +002LINE 7
IDX-FILE(IDX-KEY2 >= LINE 8    ) : +003LINE 8
IDX-FILE(IDX-KEY2 >= LINE 9    ) : +004LINE 9
== SUB-IDX-FILE-TEST-EX ==
== SUB-REL-FILE-TEST-EN ==
REL-FILE : +001LINE 6
REL-FILE : +002LINE 7
REL-FILE : +003LINE 8
REL-FILE : +004LINE 9
REL-FILE : +005LINE 10
== SUB-REL-FILE-TEST-EX ==
== SUB-IF-TEST-EN ==
MINUS : -004LINE 1
MINUS : -003LINE 2
MINUS : -002LINE 3
MINUS : -001LINE 4
PLUS : +000LINE 5
PLUS : +001LINE 6
PLUS : +002LINE 7
PLUS : +003LINE 8
PLUS : +004LINE 9
PLUS : +005LINE 10
== SUB-IF-TEST-EX ==
== SUB-EVALUATE-TEST-EN ==
MINUS : -004LINE 1
MINUS : -003LINE 2
MINUS : -002LINE 3
MINUS : -001LINE 4
ZERO : +000LINE 5
PLUS : +001LINE 6
PLUS : +002LINE 7
PLUS : +003LINE 8
PLUS : +004LINE 9
PLUS : +005LINE 10
== SUB-EVALUATE-TEST-EX ==
== SUB-PERFORM-TEST-EN ==
PERFORM I = 001
PERFORM I = 004
PERFORM I = 007
PERFORM I = 010
PERFORM I = 013
PERFORM I = 016
PERFORM I = 019
== SUB-PERFORM-TEST-EX ==
== SUB-UNSTRING-TEST-EN ==
UNSTRING-1 =(APPLE     )
UNSTRING-2 =(ORANGE    )
UNSTRING-3 =(LEMON     )
UNSTRING-4 =(PINE      )
UNSTRING-1 =(APPLE     )
UNSTRING-2 =(ORANGE    )
UNSTRING-3 =(LEMON     )
UNSTRING-4 =(PINE      )
== SUB-UNSTRING-TEST-EX ==
== SUB-INSPECT-TEST-EN ==
INSPECT-CNT = 004
WK-INSPECT(REPLACED) = aaa BBB aaa CCC aaa EEE aaa
== SUB-INSPECT-TEST-EX ==
== SUB-EDIT-TEST-EN ==
WK-EDIT-1 [123456] =      12,3456
WK-EDIT-1 [-123456] =     -12,3456
WK-EDIT-2 [123456] =      12,3456
WK-EDIT-2 [-123456] =      12,3456
== SUB-EDIT-TEST-EX ==
== SUB-COMPUTE-TEST-EN ==
WK-COMPUTE =          577.4647887323
== SUB-COMPUTE-TEST-EX ==
== SUB-DIVIDE-TEST-EN ==
DIVIDE 100/27 = +0000000003 ... +0000000019
== SUB-DIVIDE-TEST-EX ==
== SUB-VALUEHEX-TEST-EN ==
VALUE HEX = (漢字)
== SUB-VALUEHEX-TEST-EX ==
== SUB-VALUEKANJI-TEST-EN ==
VALUE KANJI = (漢字)
== SUB-VALUEKANJI-TEST-EX ==
== SUB-ACCEPT-TEST-EN ==
ACCEPT FROM SYSIN(何か入力して下さい):
適当に入力
WK-ACCEPT SYSIN = 適当に入力
WK-ACCEPT DATE = 090521
WK-ACCEPT TIME = 20181282
== SUB-ACCEPT-TEST-EX ==
== SUB-REDEFINES-TEST-EN ==
WK-REDEFINES-G = 4
WK-REDEFINES-NN = 21
WK-REDEFINES-TT = 05
WK-REDEFINES-HH = 19
== SUB-REDEFINES-TEST-EX ==
== SUB-OCCURS-TEST-EN ==
WK-OCCURS-X(001) = A
WK-OCCURS-X(002) = B
WK-OCCURS-X(003) = C
WK-OCCURS-X(004) = D
WK-OCCURS-X(005) = E
WK-OCCURS-X(006) = F
WK-OCCURS-X(007) = G
WK-OCCURS-X(008) = H
WK-OCCURS-X(009) = I
WK-OCCURS-X(010) = J
WK-OCCURS-X(011) = K
WK-OCCURS-X(012) = L
WK-OCCURS2-X(001 001) = A
WK-OCCURS2-X(001 002) = B
WK-OCCURS2-X(001 003) = C
WK-OCCURS2-X(001 004) = D
WK-OCCURS2-X(002 001) = E
WK-OCCURS2-X(002 002) = F
WK-OCCURS2-X(002 003) = G
WK-OCCURS2-X(002 004) = H
WK-OCCURS2-X(003 001) = I
WK-OCCURS2-X(003 002) = J
WK-OCCURS2-X(003 003) = K
WK-OCCURS2-X(003 004) = L
== SUB-OCCURS-TEST-EX ==
== SUB-SEARCH-TEST-EN ==
SEARCH OK KEY = 000005
SEARCH OK NAME = MIYOSHI
== SUB-SEARCH-TEST-EX ==
== SUB-FUNCTION-DATE-TEST-EN ==
WK-FUNCTION-DATE = 2009052120181282+0900
== SUB-FUNCTION-DATE-TEST-EX ==
== SUB-INITIALIZE-TEST-EN ==
WK-INITIALIZE(BEFORE) = XXXXXXX9999999XXXXXXX9999999
WK-INITIALIZE(AFTER) = XXXXXXX9999999       0000000
== SUB-INITIALIZE-TEST-EX ==