CTS-KB
RPG 1 / 5

RPG 文法基礎

#RPG #IBM i #文法

対象: RPG IV(ILE RPG)/ フリーフォーマット + RPG III(固定フォーマット)の読み方
実行環境: IBM i(AS/400)上の SEU / RDi / VSCode(Code for IBM i)
COBOL との対比は COBOL 文法基礎 を参照


目次

  1. RPGの歴史と2つの書き方
  2. プログラムの全体構造
  3. 制御仕様(ctl-opt)
  4. ファイル定義(dcl-f)
  5. データ定義(dcl-s / dcl-ds)
  6. データ型とキーワード
  7. 演算と変数操作
  8. 制御構文
  9. ファイル操作(I/O)
  10. 組み込み関数(BIF)
  11. インジケータ
  12. RPG III(固定フォーマット)の読み方
  13. コンパイルと実行

1. RPGの歴史と2つの書き方

RPG II(1970年代)

RPG III(1980年代)── 固定フォーマット(列位置が意味を持つ)

RPG IV / ILE RPG(1994年〜)── 仕様書ベース(H/F/D/C/P仕様書)

フリーフォーマット(2001年〜)── /free 〜 /end-free ブロック

完全フリーフォーマット(2013年〜 V7R1)── **free / ctl-opt / dcl-f 等

COBOL との対比

COBOL                           RPG
────────────────────            ────────────────────
IDENTIFICATION DIVISION         ctl-opt(制御仕様)
ENVIRONMENT DIVISION            dcl-f(ファイル定義)
DATA DIVISION                   dcl-s / dcl-ds(データ定義)
PROCEDURE DIVISION              メイン処理 + dcl-proc
COPY句                          /COPY, /INCLUDE
CALL + LINKAGE SECTION          callp + dcl-proc + dcl-pi
PERFORM                         exsr(サブルーチン)/ dcl-proc
READ / WRITE / REWRITE          read / write / update
IF / EVALUATE                   if / select
ファイル = SELECT ... ASSIGN    ファイル = dcl-f(DB2と直結)

最大の違い: COBOLではファイルアクセスに長いSELECT〜ASSIGN〜FD定義が必要だが、RPGでは dcl-f の1行でDB2 for iのファイルに直結する。AS/400の「OS・DB・言語が一体」というアーキテクチャの恩恵。


2. プログラムの全体構造

フリーフォーマット(RPG IV V7R1以降)

**free

// ──────────────────────────────────
// 制御仕様(COBOL の IDENTIFICATION DIVISION 相当)
// ──────────────────────────────────
ctl-opt dftactgrp(*no) actgrp(*caller) option(*nodebugio);

// ──────────────────────────────────
// ファイル定義(COBOL の ENVIRONMENT DIVISION + FD 相当)
// ──────────────────────────────────
dcl-f CUSTFILE disk(*ext) usage(*input) keyed;
dcl-f RPTFILE  printer(*ext) oflind(overflow);

// ──────────────────────────────────
// データ定義(COBOL の DATA DIVISION 相当)
// ──────────────────────────────────
dcl-s custName  char(30);
dcl-s totalAmt  packed(11:2);
dcl-s count     int(10) inz(0);

dcl-ds custRec qualified;
  id    char(8);
  name  char(30);
  addr  char(50);
end-ds;

// ──────────────────────────────────
// メイン処理(COBOL の PROCEDURE DIVISION 相当)
// ──────────────────────────────────
read CUSTFILE custRec;
dow not %eof(CUSTFILE);
  count += 1;
  exsr processCustomer;
  read CUSTFILE custRec;
enddo;

*inlr = *on;  // プログラム終了(Last Record インジケータ ON)
return;

// ──────────────────────────────────
// サブルーチン(COBOL の PERFORM 〜 SECTION 相当)
// ──────────────────────────────────
begsr processCustomer;
  // 顧客処理ロジック
endsr;

構造のまとめ

RPG プログラムの構成:

**free                          ← フリーフォーマット宣言
ctl-opt ...;                    ← 制御仕様(1つだけ)
dcl-f ...;                      ← ファイル定義(0個以上)
dcl-s / dcl-ds / dcl-c ...;    ← データ定義(0個以上)
                                ← メイン処理(ここからが実行コード)
*inlr = *on;                    ← プログラム終了
begsr ... endsr;                ← サブルーチン(0個以上)
dcl-proc ... end-proc;          ← プロシージャ(0個以上)

COBOLとの重要な違い: RPGには明確なDIVISION境界がない。ctl-optdcl-fdcl-s→メイン処理 という順序は慣例であり、コンパイラが種別を自動判定する。


3. 制御仕様(ctl-opt)

プログラム全体の設定。COBOLの IDENTIFICATION DIVISION + コンパイラオプションに相当。

ctl-opt dftactgrp(*no)       // デフォルト活性化グループを使わない
        actgrp(*caller)      // 呼び出し元の活性化グループを使う
        option(*nodebugio)   // デバッグ時にI/Oを表示しない
        datedit(*ymd)        // 日付編集形式
        datfmt(*iso);        // 日付形式 ISO

主要キーワード

キーワード意味使用頻度
dftactgrp(*no)ILE環境で動作させる(ほぼ必須)
actgrp(*caller)活性化グループを呼出元に合わせる
option(*nodebugio)デバッグ時のI/O表示を抑制
datfmt(*iso)日付形式を ISO(YYYY-MM-DD)に設定
bnddir('MYLIB/MYBND')バインディングディレクトリ指定
main(MAINPROC)リニアメインプロシージャを指定

4. ファイル定義(dcl-f)

RPGの最大の特徴。DB2 for i のファイル(テーブル)に1行で接続できる。

// 入力ファイル(キー付き読取)
dcl-f CUSTFILE disk(*ext) usage(*input) keyed;

// 更新ファイル
dcl-f ORDFILE  disk(*ext) usage(*update) keyed;

// 出力ファイル(新規書込)
dcl-f OUTFILE  disk(*ext) usage(*output);

// 印刷ファイル
dcl-f RPTPRT   printer(*ext) oflind(overflow);

// 画面ファイル(対話型プログラム)
dcl-f ORDDSP   workstn(*ext) usage(*input:*output);

COBOL との対比

COBOL(8行必要):
  SELECT CUSTFILE ASSIGN TO DATABASE-CUSTPF
    ORGANIZATION IS INDEXED
    ACCESS MODE IS DYNAMIC
    RECORD KEY IS CUST-ID.
  FD CUSTFILE.
  01 CUST-REC.
    05 CUST-ID   PIC X(8).
    05 CUST-NAME PIC X(30).

RPG(1行):
  dcl-f CUSTFILE disk(*ext) usage(*input) keyed;
  // フィールド定義はDB2のファイル定義(DDS)から自動取得

dcl-f のキーワード

キーワード意味COBOL対応
disk(*ext)外部定義のディスクファイルSELECT … ASSIGN TO DATABASE
printer(*ext)外部定義の印刷ファイルSELECT … ASSIGN TO PRINTER
workstn(*ext)画面ファイル(5250)ACCEPT/DISPLAY(CICS相当)
usage(*input)読取専用OPEN INPUT
usage(*update)読取+更新OPEN I-O
usage(*output)書込専用OPEN OUTPUT
keyedキー付きアクセスACCESS MODE IS INDEXED
oflind(overflow)オーバーフローインジケータLINAGE句
rename(FMT:NEWFMT)レコード形式名の変更(なし)
prefix(C_)フィールド名に接頭辞を付与(なし)

5. データ定義(dcl-s / dcl-ds)

スタンドアロン変数(dcl-s)

// 文字型
dcl-s custName   char(30);           // 固定長文字列
dcl-s custAddr   varchar(100);       // 可変長文字列

// 数値型
dcl-s amount     packed(11:2);       // パック10進(金額に多用)
dcl-s quantity   zoned(7:0);         // ゾーン10進
dcl-s counter    int(10);            // 4バイト整数
dcl-s bigNum     int(20);            // 8バイト整数
dcl-s rate       float(8);           // 倍精度浮動小数点

// 日付・時刻
dcl-s orderDate  date(*iso);         // 日付型
dcl-s shipTime   time(*iso);         // 時刻型
dcl-s createdAt  timestamp;          // タイムスタンプ

// インジケータ
dcl-s isValid    ind inz(*on);       // 真偽値(*on / *off)

// 初期値
dcl-s taxRate    packed(5:4) inz(0.10);  // 初期値付き
dcl-s status     char(1) inz('A');

データ構造(dcl-ds)— COBOL の 01 レコード定義に相当

// 基本的なデータ構造
dcl-ds orderRec qualified;
  ordNo    char(10);
  custId   char(8);
  ordDate  date(*iso);
  amount   packed(11:2);
  status   char(1);
end-ds;

// 使い方: orderRec.ordNo = 'A00001';

// 配列を含むデータ構造
dcl-ds orderDetail qualified dim(99);
  lineNo   packed(3:0);
  itemCd   char(10);
  qty      packed(7:0);
  price    packed(11:2);
end-ds;

// 外部定義データ構造(DDSから自動取得)
dcl-ds custDs extname('CUSTPF') qualified;
end-ds;

COBOL との対比

COBOL:                              RPG:
01 ORDER-REC.                       dcl-ds orderRec qualified;
  05 ORD-NO    PIC X(10).             ordNo    char(10);
  05 CUST-ID   PIC X(8).              custId   char(8);
  05 ORD-DATE  PIC X(10).             ordDate  date(*iso);
  05 AMOUNT    PIC S9(9)V99           amount   packed(11:2);
                COMP-3.
  05 STATUS    PIC X(1).              status   char(1);
                                    end-ds;

6. データ型とキーワード

データ型一覧

RPG型宣言例バイト数COBOL対応Cloud SQL対応
char(n)dcl-s x char(30)nPIC X(n)CHAR(n) / VARCHAR(n)
varchar(n)dcl-s x varchar(100)可変(なし)VARCHAR(n)
packed(m:n)dcl-s x packed(11:2)(m+1)/2PIC S9(m-n)V9(n) COMP-3NUMERIC(m,n)
zoned(m:n)dcl-s x zoned(7:0)mPIC S9(m-n)V9(n)NUMERIC(m,n)
int(5)dcl-s x int(5)2PIC S9(4) COMPSMALLINT
int(10)dcl-s x int(10)4PIC S9(9) COMPINTEGER
int(20)dcl-s x int(20)8PIC S9(18) COMPBIGINT
float(4)dcl-s x float(4)4COMP-1REAL
float(8)dcl-s x float(8)8COMP-2DOUBLE
datedcl-s x date(*iso)10(なし)DATE
timedcl-s x time(*iso)8(なし)TIME
timestampdcl-s x timestamp26(なし)TIMESTAMP
inddcl-s x ind1PIC 1 / 88レベルBOOLEAN

主要キーワード

キーワード意味使用例
inz(値)初期値dcl-s x int(10) inz(0)
qualified修飾名アクセス(ds.field)dcl-ds rec qualified
dim(n)配列dcl-s arr char(10) dim(100)
based(ptr)ポインタベースdcl-s x char(100) based(pBuf)
const定数dcl-c MAX_LINES 99
like(他変数)他変数と同じ型dcl-s newAmt like(amount)
extname('F[ILE](/glossary/ile)')外部ファイルから定義取得dcl-ds rec extname('CUSTPF')

7. 演算と変数操作

代入と算術

// 代入
custName = 'Honda Hiroki';
totalAmt = 0;

// 算術(自然な書き方)
totalAmt = qty * price;
taxAmt = totalAmt * taxRate;
grandTotal = totalAmt + taxAmt;

// 複合代入
count += 1;        // count = count + 1
totalAmt -= discount;

// 割り算(余りあり)
quotient = %div(dividend : divisor);
remainder = %rem(dividend : divisor);

COBOL との対比

COBOL:                              RPG:
MOVE 'Honda' TO CUST-NAME           custName = 'Honda';
COMPUTE TOTAL = QTY * PRICE         totalAmt = qty * price;
ADD 1 TO COUNT                      count += 1;

8. 制御構文

IF / ELSE

if totalAmt > 100000;
  exsr processLargeOrder;
elseif totalAmt > 10000;
  exsr processMediumOrder;
else;
  exsr processSmallOrder;
endif;

SELECT(COBOL の EVALUATE 相当)

select;
  when status = 'A';
    statusText = '有効';
  when status = 'S';
    statusText = '停止';
  when status = 'D';
    statusText = '削除';
  other;
    statusText = '不明';
endsl;

DOW(前判定ループ / COBOL の PERFORM UNTIL 相当)

read CUSTFILE custRec;
dow not %eof(CUSTFILE);
  count += 1;
  // 処理...
  read CUSTFILE custRec;
enddo;

DOU(後判定ループ)

dou response = 'Y' or response = 'N';
  dsply 'Continue? (Y/N)' '' response;
enddo;

FOR(カウンタループ / COBOL の PERFORM VARYING 相当)

for i = 1 to 100;
  totalAmt += detail(i).amount;
endfor;

ITER / LEAVE(ループ制御)

dow not %eof(ORDFILE);
  read ORDFILE orderRec;
  if orderRec.status = 'D';
    iter;  // スキップして次のループへ(COBOL の CONTINUE 相当)
  endif;
  if orderRec.amount = 0;
    leave;  // ループを抜ける(COBOL の EXIT PERFORM 相当)
  endif;
enddo;

9. ファイル操作(I/O)

RPGのファイルI/Oは非常にシンプル。DB2 for iと一体化しているため。

順次読取

dcl-f ORDFILE disk(*ext) usage(*input);

read ORDFILE orderRec;
dow not %eof(ORDFILE);
  // 処理...
  read ORDFILE orderRec;  // 次レコード
enddo;

キーによる読取(CHAIN)

dcl-f CUSTFILE disk(*ext) usage(*input) keyed;

chain custId CUSTFILE custRec;  // キーで検索
if %found(CUSTFILE);
  // 見つかった
else;
  // 見つからない
endif;

キー範囲読取(SETLL + READ)

setll startKey ORDFILE;   // 開始位置にセット
read ORDFILE orderRec;
dow not %eof(ORDFILE) and orderRec.custId = targetCust;
  // 処理...
  read ORDFILE orderRec;
enddo;

書込・更新・削除

// 書込
write ORDFMT orderRec;

// 更新(直前にreadしたレコード)
orderRec.status = 'C';
update ORDFMT orderRec;

// 削除(直前にreadしたレコード)
delete ORDFMT;

COBOL との対比

COBOL:                              RPG:
READ CUSTFILE INTO CUST-REC         read CUSTFILE custRec;
  AT END SET EOF TO TRUE            dow not %eof(CUSTFILE);
WRITE CUST-REC                      write CUSTFMT custRec;
REWRITE CUST-REC                    update CUSTFMT custRec;
DELETE CUSTFILE                      delete CUSTFMT;
START CUSTFILE KEY >= CUST-KEY      setll custKey CUSTFILE;
READ CUSTFILE KEY IS CUST-KEY       chain custKey CUSTFILE custRec;

10. 組み込み関数(BIF)

RPGの組み込み関数は % で始まる。COBOLの FUNCTION に相当するが、種類が豊富。

ファイル状態

関数意味使用例
%eof(FILE)ファイル末尾かdow not %eof(ORDFILE)
%found(FILE)レコードが見つかったかif %found(CUSTFILE)
%equal(FILE)完全一致で見つかったかif %equal(ORDFILE)
%open(FILE)ファイルが開いているかif %open(LOGFILE)

文字列操作

関数意味使用例
%trim(str)前後の空白除去name = %trim(rawName)
%trimr(str)右の空白除去code = %trimr(rawCode)
%triml(str)左の空白除去
%subst(str:pos:len)部分文字列year = %subst(date:1:4)
%scan(needle:haystack)文字列検索pos = %scan('-':phone)
%replace(new:old:pos:len)文字列置換
%len(str)長さif %len(%trim(name)) > 0
%xlate(from:to:str)文字変換upper = %xlate(lo:up:str)
%char(num)数値→文字列変換str = %char(amount)

数値操作

関数意味使用例
%dec(val:m:n)10進数変換amt = %dec(str:11:2)
%int(val)整数変換n = %int(strNum)
%div(a:b)整数除算q = %div(100:3) = 33
%rem(a:b)余りr = %rem(100:3) = 1
%abs(val)絶対値a = %abs(diff)
%editc(num:'J')数値編集カンマ区切り等

日付操作

関数意味使用例
%date()現在日付today = %date()
%time()現在時刻now = %time()
%timestamp()現在タイムスタンプts = %timestamp()
%diff(d1:d2:*days)日付差days = %diff(end:start:*days)
date + %days(n)日付加算due = ordDate + %days(30)

11. インジケータ

RPG固有の概念。COBOLにはない。真偽値フラグとして使われるが、AI解析ツールでは特に注意が必要。

概要

インジケータ = 1文字の真偽値(*on / *off)

*IN01 〜 *IN99   : 汎用インジケータ(プログラマが自由に使う)
*INLR            : Last Record(プログラム終了フラグ)
*INOF            : Overflow(帳票のページ送り)
*INKA 〜 *INKG   : ファンクションキーインジケータ

使用例

// LRインジケータ(プログラム終了)
*inlr = *on;   // これでプログラムが正常終了する

// 条件インジケータとして使う(古い書き方)
chain custId CUSTFILE;
// %found() の代わりに、以下のように書かれていることがある:
//   C     CUSTID    CHAIN     CUSTFILE              10
//   C  10          ...
// → インジケータ10 = NOT FOUND

// モダンな書き方(フリーフォーマット)
dcl-s isFound ind;
chain custId CUSTFILE;
isFound = %found(CUSTFILE);
if isFound;
  // 見つかった
endif;

AI解析での注意点

RPG IIIのコードでは、インジケータ(01〜99)が条件分岐に多用されている。コードの意味を理解するには「どのインジケータがどの条件でON/OFFされるか」を追跡する必要があり、LLMにとっては最も難しい部分の一つ。AI解析ツールのパーサーでインジケータの状態遷移を事前に注釈として付与してからLLMに渡すと精度が上がる。


12. RPG III(固定フォーマット)の読み方

メーカー・問屋の現場では、RPG IIIのソースが大量に残っている。読めなくても書ける必要はないが、AI解析ツールの入力対象として理解は必須。

仕様書の種類

各行の列6に仕様書種別を示す文字がある:

列6仕様書名役割フリーフォーマット対応
HH仕様書プログラムヘッダctl-opt
FF仕様書ファイル定義dcl-f
DD仕様書データ定義dcl-s / dcl-ds
II仕様書入力定義(不要 — 外部定義で代替)
CC仕様書計算仕様(業務ロジック)メイン処理
OO仕様書出力定義(不要 — 外部定義で代替)
PP仕様書プロシージャ境界dcl-proc / end-proc

C仕様書の列レイアウト

列位置:  1234567890123456789012345678901234567890...56789012
         |   | |         |         |    |     |    |
         行番 仕 Factor1   OpCode    Factor2  Result  インジケータ
         (1-5)(6)(7-11)   (28-32)   (33-42)  (43-48) (54-55,56-57,58-59)

C仕様書の具体例

     C           ORDAMT    ADD       TAXAMT    TOTAMT
     C           TOTAMT    COMP      LIMIT              101112
     C  10                 EXSR      APPROVE
     C  11                 EXSR      REVIEW
     C  12                 EXSR      REJECT

読み方:

  1. ORDAMT ADD TAXAMT TOTAMT → 注文金額 + 税額 = 合計金額
  2. TOTAMT COMP LIMIT → 合計金額と限度額を比較(結果インジケータ 10/11/12 にセット)
  3. インジケータ10がON → APPROVEサブルーチン実行(合計 < 限度額)
  4. インジケータ11がON → REVIEWサブルーチン実行(合計 = 限度額)
  5. インジケータ12がON → REJECTサブルーチン実行(合計 > 限度額)

F仕様書の具体例

     FCUSTFILE  IF   E           K DISK
     FRPTPRT    O    E             PRINTER OFLIND(*INOF)

読み方:

  • CUSTFILE: ファイル名
  • IF: Input(入力)+ Full-procedural
  • E: 外部定義(Externally described)
  • K: キー付き
  • DISK: ディスクファイル

13. コンパイルと実行

コンパイル(IBM i上)

// フリーフォーマットRPGLE のコンパイル
CRTBNDRPG PGM(MYLIB/MYPGM) SRCFILE(MYLIB/QRPGSRC) SRCMBR(MYPGM)

// モジュール作成(ILE)
CRTRPGMOD MODULE(MYLIB/MYMOD) SRCFILE(MYLIB/QRPGSRC) SRCMBR(MYMOD)

// プログラム作成(複数モジュール結合)
CRTPGM PGM(MYLIB/MYPGM) MODULE(MYLIB/MOD1 MYLIB/MOD2)

実行

CALL PGM(MYLIB/MYPGM)

// パラメータ付き実行
CALL PGM(MYLIB/MYPGM) PARM('PARAM1' 'PARAM2')

PUB400での実行例

// ソースファイルが HH070JP1/QRPGSRC にある場合
CRTBNDRPG PGM(HH070JP1/HELLO) SRCFILE(HH070JP1/QRPGSRC) SRCMBR(HELLO)
CALL PGM(HH070JP1/HELLO)

ローカル環境(VSCode)

RPGはIBM i上でしかコンパイル・実行できないが、VSCodeのCode for IBM i拡張を使えば、ローカルのVSCodeからPUB400に接続してソース編集・コンパイル・実行ができる。

VSCode + Code for IBM i
  → SSH でPUB400に接続
  → ローカルでソース編集
  → IBM i上でコンパイル・実行
  → 結果をVSCodeで確認

SEU(5250エディタ)を使わなくてもRPG開発が可能になるため、モダンな開発体験に近づく。


関連記事