Migaro. 技術Tips

                       

ミガロ. 製品の技術情報
IBMiの活用に役立つ情報を掲載!


【Delphi/400】IBM i 内プログラムのソースをテキスト出力

Delphi/400プログラムからCLP(CLLE)やRPG(RPGLE)を呼び出す局面において、
呼び出されたプログラムが何を行っているのかは仕様書に記載されているかと思います。

しかし、こんなケースも存在するかと思います。

  • 古いプログラムでソースは存在しても仕様書が存在しない場合
  • 仕様書を読み込むまでもないが、ざっくり内容を把握したい場合
  • 特定箇所を検索する際にエミュレータでPageUP/PageDownキーを連打したくない場合
  • 25番(ストリングの検索)はできるものの、GUIのテキスト形式で見やすくしたい場合

このような場合に、CLやRPGのソースがテキストで参照できたら……
と思われることはないでしょうか。

今回は、Delphi/400でこれらのソースをテキスト出力する方法をご紹介します。

 


参照方法

弊社環境の各ソースファイル(PF-SRC)は、以下の3つのフィールドで構成されています。
おそらく、皆様の環境でも同様かと思います。(RUNQRYで確認可)

  • SRCSEQ(行番号、数値6.2桁)
  • SRCDAT(更新日付、数値6.0桁)
  • SRCDTA(ソース内容、文字80桁または100桁)

先ほどの前置きではCLやRPGと記載しましたが、
PF-SRC形式であればDDSやCOBOLのソースでも同様です。

これをPF-DTAの物理ファイルと同じようにDelphi/400を使って読み取ることが可能です。

※書き込みも可能ですが、多くのソースでは何桁目~何桁目が何という規則が厳密にあるため推奨しません。

 


 

ご利用のDelphi/400環境で、
クエリコンポーネント(TFDQuery・TSQLQuery等)を使用して
以下のようにSQLを発行します。

SELECT * FROM LIBNAME/SRCNAME ORDER BY SRCSEQ

LIBNAMEはライブラリ名、
SRCNAMEはソースファイル名(QCLSRC・QDDSSRC等)です。
ソート順を行番号順にするため、ORDER BY句を使用しています。

 

上記のSQLをただ発行するだけだと
常にソースファイル内の先頭のメンバー(*FIRST)が参照されるため、
事前にTAS400.RemoteCmdなどでOVRDBFコマンドを発行しておくことで
対象のメンバーを参照させます。(※MBRNAMEがメンバー名)

// OVRDBFでファイルの一時変更(複数回発行した場合は上書きされる)
OVRDBF FILE(SRCNAME) TOFILE(LIBNAME/SRCNAME) MBR(MBRNAME) OVRSCOPE(*JOB)

// OVRDBFを解除する場合はDLTOVRコマンドを発行
DLTOVR FILE(SRCNAME) LVL(*JOB)

 


出力方法

上記「参照方法」で表示したレコードの値を、
上から順次参照しながらテキストに出力します。

例えば以下のようにCSV出力することが可能です。

{*******************************************************************************
 目的: CSV出力    
*******************************************************************************}
procedure TfrmB2210.Button6Click(Sender: TObject);
var
  j: Integer;
  sRow: String;
  slTEXT: TStringList;
begin

  //【※OVRDBFおよびFDQuery1を開く部分は省略】

  if (SaveDialog1.Execute) then
  begin
    slTEXT  := TStringList.Create;
    try
      // 先頭行はタイトル行とする
      sRow  := '';
      for j := 0 to (FDQuery1.FieldCount - 1) do
      begin
        sRow := sRow + AnsiQuotedStr(FDQuery1.Fields[j].FieldName, '"') + ',';
      end;
      sRow  := Copy(sRow, 1, Length(sRow) - 1); // 最後のカンマを除去
      slTEXT.Add(sRow);

      // 明細を最終行まで順次参照・テキスト出力する
      FDQuery1.First;
      while not(FDQuery1.Eof) do
      begin
        sRow   := '';
        for j  := 0 to (FDQuery1.FieldCount - 1) do
        begin
          sRow := sRow + AnsiQuotedStr(FDQuery1.Fields[j].AsString, '"') + ',';
        end;
        sRow   := Copy(sRow, 1, Length(sRow) - 1); // 最後のカンマを除去

        // 出力文字列に追加
        slTEXT.Add(sRow);

        // それ以外の場合は次行へ
        FDQuery1.Next;
      end;

      slTEXT.SaveToFile(SaveDialog1.FileName, TEncoding.UTF8); // 今回はUTF-8形式で出力
//      slTEXT.SaveToFile(SaveDialog1.FileName); // ANSI(JIS)形式で出力する場合こっち
      Application.MessageBox('出力しました。', 'Complete', 64);

    finally
      FreeAndNil(slTEXT);
    end;
  end;
end;

このロジックで、保存ダイアログで指定した場所にCSVが出力されます。
出力されたCSVは以下のようなイメージで参照できるため、
WindowsのPCでもテキスト検索ソフトなどで処理を追跡しやすくなります。

 


おまけ:CLPの逆コンパイルを行うコマンド

CLプログラム(CLP・CLLE)の場合、コンパイル時の設定で許可されていれば
プログラムからソースを抽出することが可能です。

※DDSやRPG・RPGLEではこのような設定は存在しないため、逆コンパイルは出来ません。

 

<コンパイル時の設定方法>

CL(CLLE)ソースのコンパイル時に、F4キーでプロンプトを表示し
RTVCLSRC可能 (ALWRTVSRC パラメータ) を*YESに設定します。
逆に許可させない場合は*NOに設定しておきます。

 

<逆コンパイルを行うコマンド>

IBM i エミュレータ上で、
以下のRTVCLSRC(CLソース検索)コマンドを発行します。

PGMパラメータには対象のプログラムを、
SRCFILEパラメータには復元先のQCLSRCを指定します。

(例)
RTVCLSRC PGM(LIBNAME/PGMNAME) SRCFILE(xxxLIB/QCLSRC)

この例では指定したプログラムのソースが
「xxxLIB/QCLSRC」内のメンバー「PGMNAME」として復元されます。
復元されたソースを、本記事で紹介した方法でテキスト出力することが可能になります。

※xxxLIB/QCLSRCが存在しない場合や、PGMNAMEと同名のメンバーが既に存在する場合はエラーになります。