COBOL に関する基本的なデバッグ・タスクの説明では、下記 の COBOL プログラムを参照します。
ここで述べた内容に関して詳しくは、以下のトピックを参照してください。
下記のプログラムは、デバッグ・タスクを示すために各種のトピックで取り上げられます。
このプログラムは、ローンの支払額および一連の現金のフローが 将来どう変化するかの値を計算する 2 つのサブプログラムを 呼び出します。これは、いくつかの COBOL 組み込み関数を使用します。
メインプログラム COBCALC
**********************************************************
* COBCALC *
* *
* A simple program that allows financial functions to *
* be performed using intrinsic functions. *
* *
**********************************************************
IDENTIFICATION DIVISION.
PROGRAM-ID. COBCALC.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 PARM-1.
05 CALL-FEEDBACK PIC XX.
01 FIELDS.
05 INPUT-1 PIC X(10).
01 INPUT-BUFFER-FIELDS.
05 BUFFER-PTR PIC 9.
05 BUFFER-DATA.
10 FILLER PIC X(10) VALUE "LOAN".
10 FILLER PIC X(10) VALUE "PVALUE".
10 FILLER PIC X(10) VALUE "pvalue".
10 FILLER PIC X(10) VALUE "END".
05 BUFFER-ARRAY REDEFINES BUFFER-DATA
OCCURS 4 TIMES
PIC X(10).
PROCEDURE DIVISION.
DISPLAY "CALC Begins." UPON CONSOLE.
MOVE 1 TO BUFFER-PTR.
MOVE SPACES TO INPUT-1.
* Keep processing data until END requested
PERFORM ACCEPT-INPUT UNTIL INPUT-1 EQUAL TO "END".
* END requested
DISPLAY "CALC Ends." UPON CONSOLE.
GOBACK.
* End of program.
*
* Accept input data from buffer
*
ACCEPT-INPUT.
MOVE BUFFER-ARRAY (BUFFER-PTR) TO INPUT-1.
ADD 1 BUFFER-PTR GIVING BUFFER-PTR.
* Allow input data to be in UPPER or lower case
EVALUATE FUNCTION UPPER-CASE(INPUT-1) CALC1 WHEN "END"
MOVE "END" TO INPUT-1
WHEN "LOAN"
PERFORM CALCULATE-LOAN
WHEN "PVALUE"
PERFORM CALCULATE-VALUE
WHEN OTHER
DISPLAY "Invalid input: " INPUT-1
END-EVALUATE.
*
* Calculate Loan via CALL to subprogram
*
CALCULATE-LOAN.
CALL "COBLOAN" USING CALL-FEEDBACK.
IF CALL-FEEDBACK IS NOT EQUAL "OK" THEN
DISPLAY "Call to COBLOAN Unsuccessful.".
*
* Calculate Present Value via CALL to subprogram
*
CALCULATE-VALUE.
CALL "COBVALU" USING CALL-FEEDBACK.
IF CALL-FEEDBACK IS NOT EQUAL "OK" THEN
DISPLAY "Call to COBVALU Unsuccessful.".
サブルーチン COBLOAN
**********************************************************
* COBLOAN *
* *
* A simple subprogram that calculates payment amount *
* for a loan. *
* *
**********************************************************
IDENTIFICATION DIVISION.
PROGRAM-ID. COBLOAN.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 FIELDS.
05 INPUT-1 PIC X(26).
05 PAYMENT PIC S9(9)V99 USAGE COMP.
05 PAYMENT-OUT PIC $$$$,$$$,$$9.99 USAGE DISPLAY.
05 LOAN-AMOUNT PIC S9(7)V99 USAGE COMP.
05 LOAN-AMOUNT-IN PIC X(16).
05 INTEREST-IN PIC X(5).
05 INTEREST PIC S9(3)V99 USAGE COMP.
05 NO-OF-PERIODS-IN PIC X(3).
05 NO-OF-PERIODS PIC 99 USAGE COMP.
05 OUTPUT-LINE PIC X(79).
LINKAGE SECTION.
01 PARM-1.
05 CALL-FEEDBACK PIC XX.
PROCEDURE DIVISION USING PARM-1.
MOVE "NO" TO CALL-FEEDBACK.
MOVE "30000 .09 24 " TO INPUT-1.
UNSTRING INPUT-1 DELIMITED BY ALL " "
INTO LOAN-AMOUNT-IN INTEREST-IN NO-OF-PERIODS-IN.
* Convert to numeric values
COMPUTE LOAN-AMOUNT = FUNCTION NUMVAL(LOAN-AMOUNT-IN).
COMPUTE INTEREST = FUNCTION NUMVAL(INTEREST-IN).
COMPUTE NO-OF-PERIODS = FUNCTION NUMVAL(NO-OF-PERIODS-IN).
* Calculate annuity amount required
COMPUTE PAYMENT = LOAN-AMOUNT *
FUNCTION ANNUITY((INTEREST / 12 ) NO-OF-PERIODS).
* Make it presentable
MOVE SPACES TO OUTPUT-LINE
MOVE PAYMENT TO PAYMENT-OUT.
STRING "COBLOAN:_Repayment_amount_for_a_" NO-OF-PERIODS-IN
"_month_loan_of_" LOAN-AMOUNT-IN
"_at_" INTEREST-IN "_interest_is:_"
DELIMITED BY SPACES
INTO OUTPUT-LINE.
INSPECT OUTPUT-LINE REPLACING ALL "_" BY SPACES.
DISPLAY OUTPUT-LINE PAYMENT-OUT.
MOVE "OK" TO CALL-FEEDBACK.
GOBACK.
サブルーチン COBVALU
**********************************************************
* COBVALU *
* *
* A simple subprogram that calculates present value *
* for a series of cash flows. *
* *
**********************************************************
IDENTIFICATION DIVISION.
PROGRAM-ID. COBVALU.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 CHAR-DATA.
05 INPUT-1 PIC X(10).
05 PAYMENT-OUT PIC $$$$,$$$,$$9.99 USAGE DISPLAY.
05 INTEREST-IN PIC X(5).
05 NO-OF-PERIODS-IN PIC X(3).
05 INPUT-BUFFER PIC X(10) VALUE "5069837544".
05 BUFFER-ARRAY REDEFINES INPUT-BUFFER
OCCURS 5 TIMES
PIC XX.
05 OUTPUT-LINE PIC X(79).
01 NUM-DATA.
05 PAYMENT PIC S9(9)V99 USAGE COMP.
05 INTEREST PIC S9(3)V99 USAGE COMP.
05 COUNTER PIC 99 USAGE COMP.
05 NO-OF-PERIODS PIC 99 USAGE COMP.
05 VALUE-AMOUNT OCCURS 99 PIC S9(7)V99 COMP.
LINKAGE SECTION.
01 PARM-1.
05 CALL-FEEDBACK PIC XX.
PROCEDURE DIVISION USING PARM-1.
MOVE "NO" TO CALL-FEEDBACK.
MOVE ".12 5 " TO INPUT-1.
UNSTRING INPUT-1 DELIMITED BY "," OR ALL " " VALU1
INTO INTEREST-IN NO-OF-PERIODS-IN.
* Convert to numeric values
COMPUTE INTEREST = FUNCTION NUMVAL(INTEREST-IN). VALU2
COMPUTE NO-OF-PERIODS = FUNCTION NUMVAL(NO-OF-PERIODS-IN).
* Get cash flows
PERFORM GET-AMOUNTS VARYING COUNTER FROM 1 BY 1 UNTIL
COUNTER IS GREATER THAN NO-OF-PERIODS.
* Calculate present value
COMPUTE PAYMENT =
FUNCTION PRESENT-VALUE(INTEREST VALUE-AMOUNT(ALL) ). VALU3
* Make it presentable
MOVE PAYMENT TO PAYMENT-OUT.
STRING "COBVALU:_Present_value_for_rate_of_"
INTEREST-IN "_given_amounts_"
BUFFER-ARRAY (1) ",_"
BUFFER-ARRAY (2) ",_"
BUFFER-ARRAY (3) ",_"
BUFFER-ARRAY (4) ",_"
BUFFER-ARRAY (5) "_is:_"
DELIMITED BY SPACES
INTO OUTPUT-LINE.
INSPECT OUTPUT-LINE REPLACING ALL "_" BY SPACES.
DISPLAY OUTPUT-LINE PAYMENT-OUT.
MOVE "OK" TO CALL-FEEDBACK.
GOBACK.
*
* Get cash flows for each period
*
GET-AMOUNTS.
MOVE BUFFER-ARRAY (COUNTER) TO INPUT-1.
COMPUTE VALUE-AMOUNT (COUNTER) = FUNCTION NUMVAL(INPUT-1).
ここで述べた内容に関して詳しくは、以下のトピックを参照してください。
このトピックでは、AT CALL コマンドまたは AT ENTRY コマンドを使用して、ルーチンが呼び出される直前または直後に停止する方法を説明します。 これらのコマンドの説明には、例: デバッグを行うための COBOL プログラムの例 が使用されます。
AT CALL コマンドを使用するには、呼び出すプログラムを TEST コンパイラー・オプションを使用して コンパイルしておく必要があります。
COBLOAN が呼び出される直前に停止するには、次のコマンドを入力します。
AT CALL COBLOAN ;
AT ENTRY コマンドを使用するには、呼び出したプログラムを TEST コンパイラー・オプションを使用して コンパイルしておく必要があります。
COBVALU が呼び出された直後に停止するには、次のコマンドを入力します。
AT ENTRY COBVALU ;
COBVALU が呼び出された直後に、CALL-FEEDBACK が OK である場合にのみ停止するには、以下のコマンドを入力します。
AT ENTRY COBVALU WHEN CALL-FEEDBACK = "OK" ;
プログラム内の多くのブレークポイントを設定している場合、以下のコマンドを入力して、プログラムが停止したことを Debug Tool によって特定します。
QUERY LOCATION
Debug Tool ログ・ウィンドウには、次の例と同様なものが表示されます。
QUERY LOCATION ; You were prompted because STEP ended. The program is currently entering block COBVALU.
単一の変数の内容をリストするには、ソース・ウィンドウ内の変数名の存在箇所にカーソルを移動させ、PF4(LIST) を押します。Debug Tool は、プログラム初期設定の後、シンボリック COBOL 変数が初期設定されるよりも前に、開始されるので、step または run を実行し終えるまでは、変数の内容を表示したり変更したりできないことに注意してください。値はログ・ウィンドウに表示されます。これは、コマンド行に LIST TITLED variable を入力するのと同等です。COBCALC プログラムを CALC1 というラベルの付いたステートメントまで実行し、Debug Tool コマンド行に AT 46 ; GO ; と入力します。カーソルを INPUT-1 の上に移動させ、LIST (PF4) を押します。これにより、ログ・ウィンドウに次のように表示されます。
LIST ( INPUT-1 ) ; INPUT-1 = 'LOAN '
INPUT-1 の値を変更するには、コマンド行に次のコマンドを 入力します。
MOVE 'pvalue' to INPUT-1 ;
ほとんどの COBOL の式をコマンド行に入力することができます。
次に、PF2(STEP) を押して COBVALU の呼び出しに進み、 VALU2 というラベルの付いたステートメントまで進みます。変数 INTEREST の属性を表示するには、次の Debug Tool コマンドを出します。
DESCRIBE ATTRIBUTES INTEREST ;
結果はログ・ウィンドウに次のように表示されます。
ATTRIBUTES FOR INTEREST ITS LENGTH IS 4 ITS ADDRESS IS 00011DC8 02 COBVALU:>INTEREST S999V99 COMP
このアクションは、グループ項目とデータ階層のための単純なブラウザー として使用できます。例えば、次のコマンドにより、CHAR-DATA グループの基本項目のすべての値をリストできます。
LIST CHAR-DATA ;
ログ・ウィンドウに、次のような結果が表示されます。
LIST CHAR-DATA ; 02 COBVALU:>INPUT-1 of 01 COBVALU:>CHAR-DATA = '.12 5 ' Invalid data for 02 COBVALU:>PAYMENT-OUT of 01 COBVALU:>CHAR-DATA is found. 02 COBVALU:>INTEREST-IN of 01 COBVALU:>CHAR-DATA = '.12 ' 02 COBVALU:>NO-OF-PERIODS-IN of 01 COBVALU:>CHAR-DATA = '5 ' 02 COBVALU:>INPUT-BUFFER of 01 COBVALU:>CHAR-DATA = '5069837544' SUB(1) of 02 COBVALU:>BUFFER-ARRAY of 01 COBVALU:>CHAR-DATA = '50' SUB(2) of 02 COBVALU:>BUFFER-ARRAY of 01 COBVALU:>CHAR-DATA = '69' SUB(3) of 02 COBVALU:>BUFFER-ARRAY of 01 COBVALU:>CHAR-DATA = '83' SUB(4) of 02 COBVALU:>BUFFER-ARRAY of 01 COBVALU:>CHAR-DATA = '75' SUB(5) of 02 COBVALU:>BUFFER-ARRAY of 01 COBVALU:>CHAR-DATA = '44'
ここで述べた内容に関して詳しくは、以下のトピックを参照してください。
ユーザー・プログラムの特定の部分が、最初の数千回は 正常に機能しますが、ある条件のもとでは失敗するということが よくあります。このような場合、GO を入力し続けねばならなくなる ので、行ブレークポイントをただ設定することはしたくありません。
例えば、COBVALU 内で、(例外が起こる前に) 割引率 が -1 よりも小さいか等しい場合にのみ、現在の値の計算を停止したいとします。まず、COBCALC を実行して、COBVALU に進み、 VALU1 のラベルの付いたステートメントで停止します。これを実施するには、COBCALC の始め で、次の Debug Tool コマンドを出します。
AT 67 ; GO ; CLEAR AT 67 ; STEP 4 ;
次に、以下のようにブレークポイントをセットします。
AT 44 IF INTEREST > -1 THEN GO ; END-IF ;
行 44 は、 VALU3 というラベルの付いたステートメントです。このコマンドにより、Debug Tool は行 44 で停止するようになります。INTEREST の値が -1 よりも大きい場合、プログラムは続行します。このコマンドは、INTEREST の値が -1 より小か等しい場合にのみ、Debug Tool が行 44 で停止するようにします。
割引率を強制的にマイナスにするには、次の Debug Tool コマンドを入力します。
MOVE '-2 5' TO INPUT-1 ;
GO コマンドを発行してプログラムを実行します。Debug Tool は、行 44 でプログラムを停止します。LIST INTEREST コマンドを出し、INTEREST の内容を表示します。割引率が正の場合にこのブレークポイントの効果を見るには、新しいデバッグ・セッションを開始し、当セクションで示された Debug Tool コマンドを 繰り返します。しかしこの場合、MOVE '-2 5' TO INPUT-1 コマンドは出さないでください。プログラムの実行は、行 44 で停止せず、プログラムは最後まで 実行されます。
COBVALU への入り口にブレークポイントを設定したいとします。COBVALU は、TEST を使用してコンパイルされたが、その他のプログラムはコンパイルされていません。Debug Tool は、空のソース・ウィンドウで立ち上がります。LIST NAMES CUS コマンドを使用して、COBVALU コンパイル単位が Debug Tool に認知されているかを判別できます。それから、AT APPEARANCE または AT ENTRY コマンドのどちらかを使用して適切なブレークポイントを設定します。
この例で COBVALU の入り口にブレークポイントを設定する代わりに、Debug Tool が初めに 空のソース・ウィンドウを表示したときに、STEP コマンドを出すこともできます。Debug Tool は、TEST を使用してコンパイルされた最初のルーチン (この場合、COBVALU) の入り口に達するまでプログラムを実行します。
ここで述べた内容に関して詳しくは、以下のトピックを参照してください。
通常はシステム・コンソールに表示される出力を、ユーザーの Debug Tool の端末にリダイレクトするには、次のコマンドを入力します。
SET INTERCEPT ON CONSOLE ;
例えば、COBCALC を実行して Debug Tool の SET INTERCEPT ON CONSOLE コマンドを出し、次に STEP 3 コマンドを出すと、次の出力が Debug Tool ログ・ウィンドウに表示されます。
SET INTERCEPT ON CONSOLE ; STEP 3 ; CONSOLE : CALC Begins.
CALC Begins. 句 という句は、COBCALC の中でステートメント DISPLAY "CALC Begins." UPON CONSOLE により表示されます。
SET INTERCEPT ON CONSOLE コマンドは、システム・コンソールへの出力を取り込むだけでなく、Debug Tool の INPUT コマンドを使用して、システム・コンソールの代わりにユーザーの Debug Tool 端末からデータを入力できるようにします。例えば、実行された次の COBOL ステートメント が ACCEPT INPUT-DATA FROM CONSOLE であったとすると、次のメッセージが Debug Tool のログ・ウィンドウに表示されます。
CONSOLE : IGZ0000I AWAITING REPLY. The program is waiting for input from CONSOLE. Use the INPUT command to enter 114 characters for the intercepted fixed-format file.
次の Debug Tool コマンドを入力することで、入力要求に応答し、実行を続行します。
INPUT some data ;
LIST STORAGE コマンドを使用して、変数のストレージを表示することができます。例えば、BUFFER-DATA の最初の 12 文字のストレージを表示するには、次のように入力します。
LIST STORAGE(BUFFER-DATA,12)
データの任意のセクションのみを表示することもできます。 例えば、オフセット 4 から始まる長さ 6 文字のストレージを表示するには、次のように入力します。
LIST STORAGE(BUFFER-DATA,4,6)
ここで述べた内容に関して詳しくは、以下のトピックを参照してください。
プログラミング・エラーの検討中に、どのようにしてこの状態になったのか、また特に、ルーチン呼び出しのトレースバックが何なのかを知りたいことがよくあります。この情報を得るには、次のコマンドを出します。
LIST CALLS ;
例えば、次のコマンドを使用して COBCALC の例を実行すると、
AT APPEARANCE COBVALU AT ENTRY COBVALU; GO; GO; LIST CALLS;
ログ・ウィンドウに次のように表示されます。
AT APPEARANCE COBVALU
AT ENTRY COBVALU ;
GO ;
GO ;
LIST CALLS ;
At ENTRY in COBOL program COBVALU.
From LINE 67.1 in COBOL program COBCALC.これは、呼び出し元のトレースバック情報を示しています。
プログラムを変更せずに、入り口点と出口点を示しながらプログラムをトレースするには、次の Debug Tool コマンドをファイルまたはデータ・セットに入れ、Debug Tool が最初にユーザー・プログラムを表示するときに、これを USE するようにします。次の Debug Tool コマンドを含む PDS メンバー USERID.DT.COMMANDS(COBCALC) が あるとします。
* Commands in a COBOL USE file must be coded in columns 8-72. * If necessary, commands can be continued by coding a '-' in * column 7 of the continuation line. 01 LEVEL PIC 99 USAGE COMP; MOVE 1 TO LEVEL; AT ENTRY * PERFORM; COMPUTE LEVEL = LEVEL + 1; LIST ( "Entry:", LEVEL, %CU); GO; END-PERFORM; AT EXIT * PERFORM; LIST ( "Exit:", LEVEL); COMPUTE LEVEL = LEVEL - 1; GO; END-PERFORM;
次のコマンドを入力し、このファイルを Debug Tool へのコマンドのソースとして使用することができます。
USE USERID.DT.COMMANDS(COBCALC)
USE ファイルの実行後、COBCALC を実行すると、次のトレース情報 (またはこれに類似したもの) がログ・ウィンドウに表示されます。
ENTRY: LEVEL = 00002 %CU = COBCALC ENTRY: LEVEL = 00003 %CU = COBLOAN EXIT: LEVEL = 00003 ENTRY: LEVEL = 00003 %CU = COBVALU EXIT: LEVEL = 00003 ENTRY: LEVEL = 00003 %CU = COBVALU EXIT: LEVEL = 00003 EXIT: LEVEL = 00002
USE ファイルを作成したくない場合、コマンド行から コマンドを入力しても同じ結果が得られます。
実行によって渡された段落の名前を示すトレースの生成には、次の例に示す Debug Tool コマンドを使用することができます。Debug Tool コマンド行からコマンドを入力する か、またはファイルまたはデータ・セットにコマンドを入れるかの いずれかを行うことができます。
次の Debug Tool コマンドを含む PDS メンバー USERID.DT.COMMANDS(COBCALC2) が あるとします。
* COMMANDS IN A COBOL USE FILE MUST BE CODED IN COLUMNS 8-72. * IF NECESSARY, COMMANDS CAN BE CONTINUED BY CODING A '-' IN * COLUMN 7 OF THE CONTINUATION LINE. AT GLOBAL LABEL PERFORM; LIST LINES %LINE; GO; END-PERFORM;
Debug Tool が初めてユーザーのプログラムを表示した時に、次のコマンドを入力します。
USE USERID.DT.COMMANDS(COBCALC2)
USE ファイルの実行後、COBCALC を実行することができます。すると、次のトレース (またはこれに類似したもの) がログ・ウィンドウに表示されます。
42 ACCEPT-INPUT.
59 CALCULATE-LOAN.
42 ACCEPT-INPUT.
66 CALCULATE-VALUE.
64 GET-AMOUNTS.
64 GET-AMOUNTS.
64 GET-AMOUNTS.
64 GET-AMOUNTS.
64 GET-AMOUNTS.
42 ACCEPT-INPUT.
66 CALCULATE-VALUE.
64 GET-AMOUNTS.
64 GET-AMOUNTS.
64 GET-AMOUNTS.
64 GET-AMOUNTS.
64 GET-AMOUNTS.
42 ACCEPT-INPUT.
プログラムの実行時に、あるストレージが不意にその値を変更し、いつ、どこでこのようなことが生じたかを発見したい場合があります。プログラムが、呼び出し元が想定する以上に変更を行う次のような例を考えてみます。
05 FIELD-1 OCCURS 2 TIMES
PIC X(8).
05 FIELD-2 PIC X(8).
PROCEDURE DIVISION.
* ( An invalid index value is set )
MOVE 3 TO PTR.
MOVE "TOO MUCH" TO FIELD-1( PTR ).次のコマンドにより、FIELD-2 のアドレスを見つけます。
DESCRIBE ATTRIBUTES FIELD-2
その結果が X'0000F559' であったとします。このアドレスから始まる次の 8 バイトのストレージの値の変化を監視する ブレークポイントを設定するには、次のコマンドを出します。
AT CHANGE %STORAGE(H'0000F559',8)
プログラムが実行されている時、Debug Tool は、このストレージの値が変わると 停止します。
未定義のプログラムを呼び出すと重大エラーになります。存在しないサブプログラムを呼び出すメインプログラムを作成した場合、Debug Tool がこのような呼び出しを行う直前に停止するようにできます。例えば、サブプログラム NOTYET が存在しない場合、次のようにブレークポイントを設定できます。
AT CALL (NOTYET)
Debug Tool がこのブレークポイントで停止した場合、GO BYPASS コマンドを入力して CALL をバイパスすることができます。これにより、条件を起こさずにデバッグ・セッションを続行することが できます。