久々にCOBOL

2008/06/26

CodeZineで「COBOL言語をLinux環境で動かす」という記事を見かけたので十数年ぶりにCOBOLを使ってみることにしました。

導入するのはCOBOLのオープンソース版であるOpenCOBOL、導入OSは普段メインで使っているFedora 9です。

手順はいたって簡単で、https://sourceforge.net/projects/open-cobol/からソースを入手して以下のように導入できます。

% tar zxvf open-cobol-1.0.tar.gz 
% cd open-cobol-1.0
% ./configure
% make
% sudo make install

/usr/local/binにcobcrun、cobc、cob-configの3ファイルが、/usr/local/libにlibcob.*がインストールされ、準備完了です。

まずは「Hello World」プログラムです。4つのDIVISIONを定義するところが懐かしいです。

% vi sample.cob
000001 IDENTIFICATION DIVISION.
000002 PROGRAM-ID. SAMPLE.
000003 ENVIRONMENT DIVISION.
000004 DATA DIVISION.
000005 PROCEDURE DIVISION.
000006 DISPLAY "Hello World".

最初の6桁が行番号、次の1桁が標識領域(*)までは覚えていたのですが、残りがA領域/B領域/プログラム識別番号領域に分かれているようです。

(*) 標識領域に記述できる内容は以下のとおり。

"*"または"/"

コメント行

"-"

継続行

"D"

デバッグ行

とりあえずコンパイル、実行してみます。

% cobc -x sample.cob && ./sample
Hello World

ソースはこの伝統的な固定長フォーマットの他に可変方式も選べます。コメントは先頭に"*"を付けるか、行中に"*>"を付ければOKです。

% vi sample.cob
IDENTIFICATION DIVISION.
PROGRAM-ID. SAMPLE.
ENVIRONMENT DIVISION.
DATA DIVISION.
* start proc
PROCEDURE DIVISION.
DISPLAY "Hello World". *> message

可変方式の場合、コンパイルオプションは-freeを使います。

% cobc -x -free sample.cob && ./sample 
Hello World

サンプルとして、ファイルの中身を行番号とともに表示するプログラムを作ってみました。

IDENTIFICATION DIVISION.
PROGRAM-ID. SAMPLE.
*
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
  SELECT F1 ASSIGN TO "sample.txt" STATUS STAT.
*
DATA DIVISION.
FILE SECTION.
  FD F1.                      *> ファイルディスクリプタ
  01 REC  PIC X(72).          *> レコードデータ格納変数
WORKING-STORAGE SECTION.
  01 STAT PIC X(02).          *> ファイル状況格納変数
  77 CNT  PIC 9(03).          *> 行カウンタ 
*
PROCEDURE DIVISION.
OPEN INPUT F1.
PERFORM UNTIL STAT NOT = "00" *> ファイルが使用可能
  ADD 1 TO CNT                *> 行カウンタ初期化         
  READ F1                     *> 1行読み込み
    END                       *> 読み込み終了の場合
      CONTINUE
    NOT END                   *> 1行読み込み時の処理
      DISPLAY CNT ":" REC     *> 行番号と1行データを出力
  END-READ
END-PERFORM.
CLOSE F1.
STOP RUN.

C言語のようにポインタなどをまったく意識する必要がなくコードそのものに可読性があって直感的に書けるので、COBOLが本来得意とする文書のバッチ処理などの分野ではまだまだ現役でいけるのではと思いました。

ここで突然面白いコードが書きたくなったので「3の倍数と3が付く数字のときだけアホになる」コードを書いてみました。

IDENTIFICATION DIVISION.
PROGRAM-ID. SAMPLE.
*
ENVIRONMENT DIVISION.
*
DATA DIVISION.
WORKING-STORAGE SECTION.
  77 CNT  PIC 9(03).  *> カウンタ
  77 RES  PIC 9(03).  *> 計算結果(3で割った商)
  77 REM  PIC 9(03).  *> 計算結果(3で割った余り)
  77 HAV  PIC 9(03).  *> 計算結果(3が含まれる個数)
*
PROCEDURE DIVISION.
PERFORM VARYING CNT FROM 1 BY 1 UNTIL CNT > 100
  DIVIDE CNT BY 3 GIVING RES REMAINDER REM  *> 3の倍数か
  COMPUTE HAV = 0                           *> 3が含まれる個数初期化
  INSPECT CNT TALLYING HAV FOR ALL "3"      *> 3が含まれる個数カウント
  IF REM = 0 OR HAV > 0 THEN                *> 3の倍数か、3が含まれる場合
    DISPLAY CNT ":aho"
  ELSE
    DISPLAY CNT
  END-IF
END-PERFORM.
STOP RUN.