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.