ふとCOBOL入門してみたいなと思った人向けCOBOL入門

# COBOLとは
1959年に開発された事務処理用の静的型付け言語です。
手続き型プログラミング、オブジェクト指向プログラミング、命令型プログラミングが可能です。
英文を書くようにプログラムを書けることが特徴ですが、別に現代的な書き方をすることもできます。

# なぜ今更COBOLを入門する必要があるのか？
そんなこと考える人はこの記事を読まないと思います。

# COBOLコンパイラ
GnuCOBOL、opensource COBOL、OpenCobolを始めとして、様々なフリーコンパイラが公開されています。
この記事では、筆者がWindowsを使っているのでWindows上で導入が楽なOpenCOBOLを使用することとします。

# OpenCobolの環境構築
前述しましたが筆者はWindowsを使ってるので、MacとLinux向けの環境構築手順は参考になりそうな別の記事を紹介するだけにします。

## Windows
IDEをインストールする方法が１番楽だと思います。
OpenCobolIDEという、OpenCobol専用みたいなIDEを入れるだけでCOBOLのコーディング・実行ができます。
↓より取得できます。

[Download project files](https://launchpad.net/cobcide/+download)

## Mac
なんとなくこの記事が参考になりそうです。

[MacにCobolを入れていじってみた話](https://qiita.com/yhinoz/items/125ff9809f74f5890a33)

## Linux
なんとなくこの記事が参考になりそうです。

[COBOL言語をLinux環境で動かす](https://codezine.jp/article/detail/2291)

# COBOLは列番号に意味がある

以下のHello, World!を出力するソースコードを参考にしましょう。

```cobol
000100 IDENTIFICATION DIVISION.
000200 PROGRAM-ID. HELLO-WORLD.
000300 PROCEDURE DIVISION.
000400 MAIN-PROCEDURE.
000500      DISPLAY "Hello, World!"
000600 STOP RUN.
000700 END PROGRAM HELLO-WORLD.
```

ここで、列に注目してみましょう。
1~6列目はなにやら連番で数字が書いてあり、7列目は空白、8列目からプログラムっぽいのが書かれてますね。

COBOLでは、各列領域に役割が与えられています。
以下、その各列領域の役割を書いた表を記します。

|何列目|領域名|役割|
|-----|-----|---|
|1~6列目|一連番号|プログラムの行を識別するために６桁の番号を書きます。|
|7列目|標準領域|その行の標識を書く。例えばスペースならその行は命令行であることを示し、*ならその行は注釈（コメント）行であることを示す。|
|8~11列目|A領域|各部や節の見出し段落の見出し等を記述します。|
|12~72列目|B領域|各段落を構成する文（命令文も含む）を記述する場所です。ピリオドも必ずこの中で収まるようにしなければなりません。|
|73~80目|プログラム識別領域|全てコメントとして扱われます。|

ちなみに、1~6列目の一連番号領域はコンパイル時に無視されるので、別にスペースでも良いです。以降COBOLのコードを書くときは一連番号領域は全てスペースにします。

# 予約語について
大抵の言語もそうですが、例えば変数（COBOLでは変数のことをデータ項目と言う）を宣言する際に予約語は使用できません。

プログラマが使えるのは利用者定義語といい、以下のように使うことができます。

- 英字・数字・ハイフンの文字の任意の組合せ
- 30文字以内(プログラム名は8文字以内)
- 先頭・最後にハイフン使用不可
- システム名、予約語と同じ文字列を定義してはならない 

# 部・節・段落
COBOLのプログラムを構成する要素として、部（DIVISION）があります。
部からさらに節、段落と要素が分かれていきます。

先ほどのHello, World!のプログラムをもう１度見てみましょう。（一連番号は全てスペースにしてある）

```cobol
       IDENTIFICATION DIVISION.
       PROGRAM-ID. HELLO-WORLD.
       PROCEDURE DIVISION.
       MAIN-PROCEDURE.
            DISPLAY "Hello, World!"
       STOP RUN.
       END PROGRAM HELLO-WORLD.
```

いくつかの場所にDIVISIONという言葉がありますね。

COBOLプログラムは４つの部（DIVISION）から構成されます。

## IDENTIFICATION DIVISION（見出し部）
プログラム名などを記述します。

## ENVIRONMENT DIVISION（環境部）
使用するファイル、環境変数などがあればここで記述します。

## DATA DIVISION（データ部）
プログラム中に使用するデータ（いわゆる変数）を宣言しておきます。

## PROCEDURE DIVISION（手続き部）
実際の処理内容を記述します。ちなみにPROCEDURE DIVISION内の命令文はピリオドが不要です。

## あれ？さっきのHello, World!のコードの中に使われてないDIVISIONあるくね？
はい、別に使わない部があれば省略しちゃっても問題はないです。
例えば先ほどのHello, World!のプログラムでは、ファイル・環境変数などは使用していませんし、何らかのデータを使ってもいません。
ですのでENVIRONMENT DIVISION（環境部）とDATA DIVISION（データ部）は書いていません。

# COBOLのデータ定義
以下のプログラムを見てみます。

```cobol
       IDENTIFICATION DIVISION.
       PROGRAM-ID. HELLO-WORLD.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 HELLO PIC X(5).
       PROCEDURE DIVISION.
       MAIN-PROCEDURE.
            MOVE "Hello" TO HELLO
            DISPLAY HELLO ", World!"
       STOP RUN.
       END PROGRAM HELLO-WORLD.
```

実行結果は
`Hello, World!`
と出力されます。

前にあげた普通のHello, World!のプログラムと何が違うか解説します。

まずHELLOという任意の文字が５文字入るデータを定義しておきます。そしてHELLOに"Hello"という文字をいれ、HELLOと", World!"を標準出力しています。

## DATA DIVISIONにおけるデータ定義方法

さきほどのプログラムをDATA DIVISIONのみに注目して見てみましょう。

```cobol
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 HELLO PIC X(5).
```

[部・節・段落](#部・節・段落)で、COBOLプログラムは４つの部から構成され、各部からさらに節・段落と分けられていく、みたいなこと言いましたよね。

DATA DIVISIONでデータ定義をするときは、WORKING-STORAGE SECTIONという節の下でします。

ここで、

```cobol
01 HELLO PIC X(5).
```
で実際にデータ定義をしてます。
01という数字はレベル番号と言い、もう少し後で詳しく説明します。
HELLOはデータ項目名、他の言語だと変数名と言います。予約語でなければ自由に命名できます。
PICはPICTURE句といい、そのデータの型や長さを指定するために付けます。
PICはPICTUREの略なので、

```cobol
01 HELLO PIC X(5).
```
と

```cobol
01 HELLO PICTURE X(5).
```
は同じです。

## COBOLのデータ型
先ほどのデータ定義方法であげたとこの`X(5)`とかですね。

|タイプ識別子|内容|
|----------|---|
|9|10進の自然数１桁|
|S|符号付の数字|
|V|小数点の位置|
|X|任意の文字|

この他にも色々あります。

各タイプ識別子に、()を付けて桁数を指定することができます。

例えば、
`9(3)`は10進整数3桁、`9(3)V9(2)`は10進整数部2桁小数部2桁の数字になります。

ちなみに`9(3)`は`999`とも書けます。
なので`9(3)V9(2)`は`999V99`と同じです。

## レベル番号

```cobol
01 HELLO PIC X(5).
```
を見て思ったと思います。
「01ってなんやねん。」

01はレベル番号と言い、そのデータ項目の階層や従属関係を表すことができます。

例えば、[COBOLのデータ定義](http://tallercolibri.com/archives/104)から引用させて頂きますが、

```cobol
01  従業員.
    03  従業員コード  PIC 9(6).
    03  従業員名  PIC  X(30).
    03  入社日付.
        05  年  PIC 9999.
        05  月  PIC 99.
        05  日  PIC 99.
```

という書き方ができます。

ここで、従業員や入社日付は集団項目、従業員コードや従業員名、年、月、日は基本項目と言います。

集団項目は複数の基本項目や集団項目が集まるデータ項目、基本項目はこれ以上分類できないデータ項目です。

下の階層になるにつれて、その階層や従属関係を表すためにレベル番号を付けていくという感じです。

ちなみに先ほどの例は01, 03と奇数がつけられていますが、これは後でデータの追加をしやすくするためらしいです。

## データに値を入れる
定義したデータに実際の値を入れる方法を２つ挙げます。
今から下に挙げるCOBOLプログラムは同じ処理をしています。

```cobol
       IDENTIFICATION DIVISION.
       PROGRAM-ID. ENZAN.
       DATA DIVISION.
       FILE SECTION.
       WORKING-STORAGE SECTION.
       01 A PIC 9(3) VALUE 5.
       PROCEDURE DIVISION.
       MAIN-PROCEDURE.
            DISPLAY A
            STOP RUN.
       END PROGRAM ENZAN.
```

```cobol
       IDENTIFICATION DIVISION.
       PROGRAM-ID. ENZAN.
       DATA DIVISION.
       FILE SECTION.
       WORKING-STORAGE SECTION.
       01 A PIC 9(3).
       PROCEDURE DIVISION.
       MAIN-PROCEDURE.
            MOVE 5 TO A
            DISPLAY A
            STOP RUN.
       END PROGRAM ENZAN.
```

１つめが、DATA DIVISIONで
`01 A PIC 9(3) VALUE 5.`のように、`VALUE 値`を付けることでデータ定義時に同時に値を代入する方法です。

２つめが、DATA DIVISIONでデータ定義だけしておいて、命令部で`MOVE 5 TO A`と書き値を代入する方法です。

# 四則演算
英文を書くようにコードを書く方法と、ごく普通のプログラミング言語風に書く方法があります。

## 英文的
以下は、AとBとSUM-DATAという２つのデータを定義し、Aには5、Bには6をいれます。そして、AにBを加えその結果をSUM-DATAに入れています。

```cobol
       IDENTIFICATION DIVISION.
       PROGRAM-ID. ENZAN.
       DATA DIVISION.
       FILE SECTION.
       WORKING-STORAGE SECTION.
       01 A PIC 9(3) VALUE 6.
       01 B PIC 9(3) VALUE 5.
       01 SUM-DATA PIC 9(3).
       PROCEDURE DIVISION.
       MAIN-PROCEDURE.
            ADD A B TO SUM-DATA
            DISPLAY SUM-DATA
            STOP RUN.
       END PROGRAM ENZAN.
```

SUM-DATA=A+Bをしている部分は
`ADD A B TO SUM-DATA`です。
めっちゃ英文的ですね。

同じように減算、乗算、除算の方法も書いておきます。
演算結果を入れるデータ項目名が全部SUM-DATAのは命名がクソですが気にしないでください。

- 減算
`SUBTRACT A FROM B GIVING SUM-DATA`
- 乗算
`MULTIPLY A BY B GIVING SUM-DATA`
- 除算
`DIVIDE A BY B GIVING SUM-DATA`

## 現代的
COMPUTE句を使います。

- 加算
`COMPUTE SUM-DATA = A + B`
- 減算
`COMPUTE SUM-DATA = A - B`
- 乗算
`COMPUTE SUM-DATA = A * B`
- 除算
`COMPUTE SUM-DATA = A / B`

# とりあえずこれで終わりにしとく
条件分岐とか繰り返しとかはまた気が向いたら書きます。
間違えたことを書いていたらコメントでご指摘頂ければ幸いです。

# 参考にした記事など
- [サルでもわかるCOBOL入門](http://www16.plala.or.jp/hiyokogumi/top.html)
- [COBOLプログラミング入門](http://tallercolibri.com/)
- [COBOL入門](https://www.cobol.co.jp/cobol-nyuumon/)