対象: RPG IV(ILE RPG)/ フリーフォーマット + RPG III(固定フォーマット)の読み方
実行環境: IBM i(AS/400)上の SEU / RDi / VSCode(Code for IBM i)
COBOL との対比は COBOL 文法基礎 を参照
目次
- RPGの歴史と2つの書き方
- プログラムの全体構造
- 制御仕様(ctl-opt)
- ファイル定義(dcl-f)
- データ定義(dcl-s / dcl-ds)
- データ型とキーワード
- 演算と変数操作
- 制御構文
- ファイル操作(I/O)
- 組み込み関数(BIF)
- インジケータ
- RPG III(固定フォーマット)の読み方
- コンパイルと実行
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-opt→dcl-f→dcl-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) | n | PIC 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)/2 | PIC S9(m-n)V9(n) COMP-3 | NUMERIC(m,n) |
zoned(m:n) | dcl-s x zoned(7:0) | m | PIC S9(m-n)V9(n) | NUMERIC(m,n) |
int(5) | dcl-s x int(5) | 2 | PIC S9(4) COMP | SMALLINT |
int(10) | dcl-s x int(10) | 4 | PIC S9(9) COMP | INTEGER |
int(20) | dcl-s x int(20) | 8 | PIC S9(18) COMP | BIGINT |
float(4) | dcl-s x float(4) | 4 | COMP-1 | REAL |
float(8) | dcl-s x float(8) | 8 | COMP-2 | DOUBLE |
date | dcl-s x date(*iso) | 10 | (なし) | DATE |
time | dcl-s x time(*iso) | 8 | (なし) | TIME |
timestamp | dcl-s x timestamp | 26 | (なし) | TIMESTAMP |
ind | dcl-s x ind | 1 | PIC 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 | 仕様書名 | 役割 | フリーフォーマット対応 |
|---|---|---|---|
| H | H仕様書 | プログラムヘッダ | ctl-opt |
| F | F仕様書 | ファイル定義 | dcl-f |
| D | D仕様書 | データ定義 | dcl-s / dcl-ds |
| I | I仕様書 | 入力定義 | (不要 — 外部定義で代替) |
| C | C仕様書 | 計算仕様(業務ロジック) | メイン処理 |
| O | O仕様書 | 出力定義 | (不要 — 外部定義で代替) |
| P | P仕様書 | プロシージャ境界 | 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
読み方:
ORDAMT ADD TAXAMT TOTAMT→ 注文金額 + 税額 = 合計金額TOTAMT COMP LIMIT→ 合計金額と限度額を比較(結果インジケータ 10/11/12 にセット)- インジケータ10がON →
APPROVEサブルーチン実行(合計 < 限度額) - インジケータ11がON →
REVIEWサブルーチン実行(合計 = 限度額) - インジケータ12がON →
REJECTサブルーチン実行(合計 > 限度額)
F仕様書の具体例
FCUSTFILE IF E K DISK
FRPTPRT O E PRINTER OFLIND(*INOF)
読み方:
CUSTFILE: ファイル名IF: Input(入力)+ Full-proceduralE: 外部定義(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開発が可能になるため、モダンな開発体験に近づく。
関連記事
- COBOL 文法基礎 — COBOL の対応する文法リファレンス
- RPG モジュール設計 — サブルーチンとモジュール化
- RPG 業務ロジック実装 — 受注・在庫・出荷の実装例
- RPG × SQL 連携 — 埋め込み SQL によるデータベースアクセス
- RPG 本番運用 — IBM i での帳票・画面・ジョブ管理