Rational Developer for System z, Version 7.6

Debugging a COBOL program in full-screen mode

The descriptions of basic debugging tasks for COBOL refer to the following COBOL program.

Example: sample COBOL program for debugging

Refer to the following topics for more information related to the material discussed in this topic.

Example: sample COBOL program for debugging

The program below is used in various topics to demonstrate debugging tasks.

This program calls two subprograms to calculate a loan payment amount and the future value of a series of cash flows. It uses several COBOL intrinsic functions.

Main program 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.".

Subroutine 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.

Subroutine 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).

Refer to the following topics for more information related to the material discussed in this topic.

Halting when certain routines are called in COBOL

This topic describes how to halt just before or just after a routine is called by using the AT CALL or AT ENTRY commands. The Example: sample COBOL program for debugging is used to describe these commands.

To use the AT CALL command, you must compile the calling program with the TEST compiler option.

To halt just before COBLOAN is called, enter the following command:

AT CALL COBLOAN ;

To use the AT ENTRY command, you must compile the called program with the TEST compiler option.

To halt just after COBVALU is called, enter the following command:

AT ENTRY COBVALU ;

To halt just after COBVALU is called and only when CALL-FEEDBACK equals OK, enter the following command:

AT ENTRY COBVALU WHEN CALL-FEEDBACK = "OK" ;

Identifying the statement where your COBOL program has stopped

If you have many breakpoints set in your program, enter the following command to have Debug Tool identify your program has been stopped:

QUERY LOCATION

The Debug Tool Log window displays something similar to the following example:

QUERY LOCATION ;
You were prompted because STEP ended.
The program is currently entering block COBVALU.

Modifying the value of a COBOL variable

Example: sample COBOL program for debugging

To list the contents of a single variable, move the cursor to an occurrence of the variable name in the Source window and press PF4 (LIST). Remember that Debug Tool starts after program initialization but before symbolic COBOL variables are initialized, so you cannot view or modify the contents of variables until you have performed a step or run. The value is displayed in the Log window. This is equivalent to entering LIST TITLED variable on the command line. Run the COBCALC program to the statement labeled  CALC1 , and enter AT 46 ; GO ; on the Debug Tool command line. Move the cursor over INPUT-1 and press LIST (PF4). The following appears in the Log window:

 LIST ( INPUT-1 ) ;
INPUT-1 = 'LOAN      '

To modify the value of INPUT-1, enter on the command line:

MOVE 'pvalue' to INPUT-1 ;

You can enter most COBOL expressions on the command line.

Now step into the call to COBVALU by pressing PF2 (STEP) and step until the statement labeled  VALU2  is reached. To view the attributes of the variable INTEREST, issue the Debug Tool command:

DESCRIBE ATTRIBUTES INTEREST ;

The result in the Log window is:

ATTRIBUTES FOR INTEREST
  ITS LENGTH IS 4
  ITS ADDRESS IS 00011DC8
  02 COBVALU:>INTEREST   S999V99 COMP

You can use this action as a simple browser for group items and data hierarchies. For example, you can list all the values of the elementary items for the CHAR-DATA group with the command:

LIST CHAR-DATA ;

with results in the Log window appearing something like this:

 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'
Note:
If you use the LIST command to list the contents of an uninitialized variable, or a variable that contains invalid data, Debug Tool displays INVALID DATA.

Refer to the following topics for more information related to the material discussed in this topic.

Halting on a COBOL line only if a condition is true

Often a particular part of your program works fine for the first few thousand times, but it fails under certain conditions. You don't want to just set a line breakpoint because you will have to keep entering GO.

Example: sample COBOL program for debugging

For example, in COBVALU you want to stop at the calculation of present value only if the discount rate is less than or equal to -1 (before the exception occurs). First run COBCALC, step into COBVALU, and stop at the statement labeled  VALU1 . To accomplish this, issue these Debug Tool commands at the start of COBCALC:

AT 67 ; GO ;
CLEAR AT 67 ; STEP 4 ;

Now set the breakpoint like this:

AT 44 IF INTEREST > -1 THEN GO ; END-IF ;

Line 44 is the statement labeled  VALU3 . The command causes Debug Tool to stop at line 44. If the value of INTEREST is greater than -1, the program continues. The command causes Debug Tool to remain on line 44 only if the value of INTEREST is less than or equal to -1.

To force the discount rate to be negative, enter the Debug Tool command:

MOVE '-2 5' TO INPUT-1 ;

Run the program by issuing the GO command. Debug Tool halts the program at line 44. Display the contents of INTEREST by issuing the LIST INTEREST command. To view the effect of this breakpoint when the discount rate is positive, begin a new debug session and repeat the Debug Tool commands shown in this section. However, do not issue the MOVE '-2 5' TO INPUT-1 command. The program execution does not stop at line 44 and the program runs to completion.

Debugging COBOL when only a few parts are compiled with TEST

Example: sample COBOL program for debugging

Suppose you want to set a breakpoint at entry to COBVALU. COBVALU has been compiled with TEST but the other programs have not. Debug Tool comes up with an empty Source window. You can use the LIST NAMES CUS command to determine if the COBVALU compile unit is known to Debug Tool and then set the appropriate breakpoint using either the AT APPEARANCE or the AT ENTRY command.

Instead of setting a breakpoint at entry to COBVALU in this example, issue a STEP command when Debug Tool initially displays the empty Source window. Debug Tool runs the program until it reaches the entry for the first routine compiled with TEST, COBVALU in this case.

Refer to the following topics for more information related to the material discussed in this topic.

Capturing COBOL I/O to the system console

To redirect output normally appearing on the system console to your Debug Tool terminal, enter the following command:

SET INTERCEPT ON CONSOLE ;

Example: sample COBOL program for debugging

For example, if you run COBCALC and issue the Debug Tool SET INTERCEPT ON CONSOLE command, followed by the STEP 3 command, you will see the following output displayed in the Debug Tool Log window:

SET INTERCEPT ON CONSOLE ;
STEP 3 ;
CONSOLE : CALC Begins.

The phrase CALC Begins. is displayed by the statement DISPLAY "CALC Begins." UPON CONSOLE in COBCALC.

The SET INTERCEPT ON CONSOLE command not only captures output to the system console, but also allows you to input data from your Debug Tool terminal instead of the system console by using the Debug Tool INPUT command. For example, if the next COBOL statement executed is ACCEPT INPUT-DATA FROM CONSOLE, the following message appears in the Debug Tool Log window:

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.

Continue execution by replying to the input request by entering the following Debug Tool command:

INPUT some data ;
Note:
Whenever Debug Tool intercepts system console I/O, and for the duration of the intercept, the display in the Source window is empty and the Location field in the session panel header at the top of the screen shows Unknown.

Displaying raw storage in COBOL

You can display the storage for a variable by using the LIST STORAGE command. For example, to display the storage for the first 12 characters of BUFFER-DATA enter:

LIST STORAGE(BUFFER-DATA,12)

You can also display only a section of the data. For example, to display the storage that starts at offset 4 for a length of 6 characters, enter:

LIST STORAGE(BUFFER-DATA,4,6)

Refer to the following topics for more information related to the material discussed in this topic.

Getting a COBOL routine traceback

Often when you get close to a programming error, you want to know how you got into that situation, and especially what the traceback of calling routines is. To get this information, issue the command:

LIST CALLS ;

Example: sample COBOL program for debugging

For example, if you run the COBCALC example with the commands:

AT APPEARANCE COBVALU AT ENTRY COBVALU;
GO;
GO;
LIST CALLS;

the Log window contains something like:

 AT APPEARANCE COBVALU
   AT ENTRY COBVALU ;
 GO ;
 GO ;
 LIST CALLS ;
At ENTRY in COBOL program COBVALU.
From LINE 67.1 in COBOL program COBCALC.

which shows the traceback of callers.

Tracing the run-time path for COBOL code compiled with TEST

To trace a program showing the entry and exit points without requiring any changes to the program, place the following Debug Tool commands in a file or data set and USE them when Debug Tool initially displays your program. Assuming you have a PDS member, USERID.DT.COMMANDS(COBCALC), that contains the following Debug Tool commands:

* 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;

You can use this file as the source of commands to Debug Tool by entering the following command:

USE USERID.DT.COMMANDS(COBCALC)

If, after executing the USE file, you run COBCALC, the following trace (or similar) is displayed in the Log window:

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

If you do not want to create the USE file, you can enter the commands through the command line, and the same effect is achieved.

Generating a COBOL run-time paragraph trace

To generate a trace showing the names of paragraphs through which execution has passed, the Debug Tool commands shown in the following example can be used. You can either enter the commands from the Debug Tool command line or place the commands in a file or data set.

Example: sample COBOL program for debugging

Assume you have a PDS member, USERID.DT.COMMANDS(COBCALC2), that contains the following Debug Tool commands.

* 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;

When Debug Tool initially displays your program, enter the following command:

USE USERID.DT.COMMANDS(COBCALC2)

After executing the USE file, you can run COBCALC and the following trace (or similar) is displayed in the Log window:

      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.

Finding unexpected storage overwrite errors in COBOL

During program run time, some storage might unexpectedly change its value and you want to find out when and where this happened. Consider this example where the program changes more than the caller expects it to change.

   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 ).

Find the address of FIELD-2 with the command:

DESCRIBE ATTRIBUTES FIELD-2

Suppose the result is X'0000F559'. To set a breakpoint that watches for a change in storage values starting at that address for the next 8 bytes, issue the command:

AT CHANGE %STORAGE(H'0000F559',8)

When the program runs, Debug Tool halts if the value in this storage changes.

Halting before calling an invalid program in COBOL

Calling an undefined program is a severe error. If you have developed a main program that calls a subprogram that doesn’t exist, you can cause Debug Tool to halt just before such a call. For example, if the subprogram NOTYET doesn't exist, you can set the breakpoint:

AT CALL (NOTYET)

When Debug Tool stops at this breakpoint, you can bypass the CALL by entering the GO BYPASS command. This allows you to continue your debug session without raising a condition.


Terms of use | Feedback

This information center is powered by Eclipse technology. (http://www.eclipse.org)