PL/I condition handling example

The following example shows an example of condition handling for PL/I.
*PROCESS MACRO;
 /*Module/File Name: IBMDIVZ
 /*********************************************************************/
 /*                                                                   */
 /* PL/I Condition Handling Functions:                                */
 /*                : Establish ZERODIVIDE ON-unit                     */
 /*                : GO TO out of ZERODIVIDE ON-unit                  */
 /*                : PL/I Normal return from ZERODIVIDE ON-unit       */
 /*                : Revert ZERODIVIDE ON-unit                        */
 /*                : PL/I System action on ZERODIVIDE condition       */
 /*                                                                   */
 /* 1. This example establishes a ZERODIVIDE ON-unit.                 */
 /* 2. A subprogram, sdivide, is called and causes a ZERODIVIDE       */
 /*    condition to occur.                                            */
 /* 3. The ZERODIVIDE ON-unit is entered. A GOTO out of the ON-unit   */
 /*    is processed.  The program resumes at the label                */
 /*    "after_1st_zerodivide".                                        */
 /* 4. A new ZERODIVIDE ON-unit is established and it overrides the   */
 /*    current established ZERODIVIDE ON-unit.                        */
 /* 5. The subroutine sdivide is called a second time.                */
 /* 6. The newly established ZERODIVIDE ON-unit is entered. A GOTO    */
 /*    is not executed, and the program resumes at the location       */
 /*    following the instruction that caused the condition. This      */
 /*    is the PL/I normal return action for the ZERODIVIDE condition. */
 /* 7. The established ZERODIVIDE ON-unit is canceled by executing    */
 /*    the REVERT ZERODIVIDE statement.                               */
 /* 8. Sdivide is called a third time.  Because there is no           */
 /*    ZERODIVIDE ON-unit established, the PL/I implicit action       */
 /*    is executed. Namely, the ERROR condition is raised and the     */
 /*    program is terminated.                                         */
 /**                                                                  */
 /*********************************************************************/

 CEPLCND: Proc Options(Main);

    %INCLUDE  CEEIBMAW;
    %INCLUDE  CEEIBMCT;
    dcl in_zdiv_ou1 char (1), in_zdiv_ou2 char(1),fell_thru char(1);
    in_zdiv_ou1 = 'N';
    in_zdiv_ou2 = 'N';
    fell_thru = 'N';
    /****************************************************************/
    /* A ZERODIVIDE ON-unit is established when control reaches the */
    /* ON statement.                                                */
    /****************************************************************/
     on zerodivide begin;
        in_zdiv_ou1 = 'Y';
        go to after_1st_zerodivide;
        end;

    /****************************************************************/
    /* The first call to sdivide will result in the ZERODIVIDE      */
    /* condition being raised. The preceding established ON-unit    */
    /* gets control.  Due to a GO TO out of the ON-unit, execution  */
    /* resumes immediately at label after_1st_zerodivide. This is   */
    /* verified by checking that the flow of control did not resume */
    /* at the instruction following the ZERODIVIDE condition.       */
    /****************************************************************/
    call sdivide;after_1st_zerodivide:
    if (fell_thru = 'Y') then do;
       put skip list ('Error in flow of control after'
          || ' the first call to sdivide. ');
       end;
    /****************************************************************/
    /* A new ZERODIVIDE ON-unit is established when control         */
    /* reaches the following ON ZERODIVIDE statement.               */
    /****************************************************************/
    on zerodivide begin;
       in_zdiv_ou2 = 'Y';
       end;

    /****************************************************************/
    /* Subroutine sdivide is called a second time to raise the      */
    /* ZERODIVIDE condition.  Control enters the established        */
    /* ZERODIVIDE ON-unit.  On exit from the preceding zerodivide   */
    /* ON-unit, control returns to the instruction following the    */
    /* divide by zero in subroutine SDIVIDE.  A check is made to    */
    /* detect if control flowed to the instruction following the    */
    /* one that caused the zerodivide condition to be raised.       */
    /****************************************************************/
    call sdivide;
    if (fell_thru = 'N') then do;
       put skip list
          ('Error in flow of control after second call to cepldiv. ');
       end;
    /****************************************************************/
    /* The ZERODIVIDE  ON-unit is canceled by action of the         */
    /* REVERT statement.                                            */
    /****************************************************************/
    revert zerodivide;
    if (in_zdiv_ou1 = 'N' | in_zdiv_ou2 = 'N') then
       put skip list ('Error in flow of control to ON-units');
    else  do;
       put skip list ('The PL/I condition handling example'
          || ' will terminate with PL/I message IBM0301');

       /*************************************************************/
       /* Sdivide is called for the third and final time. Because   */
       /* there are no established ON-units, the implicit action    */
       /* for ZERODIVIDE takes place.                               */
       /*************************************************************/
       call sdivide;
       put skip list ('Error in flow of control after third'
          || ' call to sdivide. ');
       end;

 /*******************************************************************/
 /* The sdivide subroutine causes a ZERODIVIDE condition.           */
 /*******************************************************************/
 sdivide: proc;
      dcl int fixed bin (15,0);
      dcl int_2 fixed bin (15,0) init(5);
      dcl int_3 fixed bin (15,0) init(0);
      int = int_2 / int_3;
      fell_thru = 'Y';
 end sdivide;

 End ceplcnd;