Wednesday, May 17, 2023

Capturing errors within ON-EXIT

Having been busy recently performing presentations to various user groups and conferences I noticed an oversight in my work. In my presentations I had given an example of using the ON-EXIT group showing how I can use an indicator to indicate if an error had occurred in the procedure or subprocedure. In my post, on this website, about ON-EXIT I only mentioned it in passing. In this post I want to overcome oversight to show how I can do this.

The ON-EXIT group can be added to the end of every procedure or subprocedure in a RPG program. Regardless of whether the procedure or subprocedures errors or not, the code within the ON-EXIT group is always executed.

Let me start with my first example program, this one does not have any procedures or subprocedures:

01  **free
02  dcl-s Number int(3) ;

03  Number = Number / Number ; 

04  dsply ('After division') ;

05  *inlr = *on ;

Line 1: In 2023 we should all be coding in totally free format RPG.

Line 2: Defining an integer variable.

Line 3: This line will cause an error as I cannot divide zero by zero. Usually I would put this calculation within a Monitor group to handle any errors. But here I want this calculation to error, and it not be handled.

Line 4: If line 3 does not error then this Display operation code, DSPLY, will be performed.

Line 5: End of program.

After compiling the program I call it and the following error message is received:

Attempt to divide by zero (C G D F).

When the error occurs and I answer the message, with "C", the program ends. There is not a way I can handle this error.

My next example uses a Main procedure:

01  **free
02  ctl-opt main(Main) dftactgrp(*no) ;

03  dcl-proc Main ;
04    dcl-s Number int(3) ;
05    dcl-s ErrorHappened ind ;

06    Number = Number / Number ;

07    dsply ('After division') ;

08  on-exit ErrorHappened ;
09    if (ErrorHappened) ;
10      dsply ('Error happened') ;
11    else ;
12      dsply ('Everyting is OK') ;
13    endif ;
14  end-proc ;

This program is pretty similar to the previous one, there are just few things I want you to notice.

Line 5: I have defined an indicator variable.

Line 8: The start of my ON-EXIT group. The indicator is also on this line. It will be "on" if there is an error, and "off" if there is not. I do not have to set the indicator one way or another in procedure, in case of an error it is set "on" without me having to do anything.

Lines 9 – 13: This If statement will send a message, using the DSPLY operation code, if there was an error.

Compiled the program, called it, and these was the only message displayed:

DSPLY  Error happened

I have stopped the program from "hard erroring" with the message as happened in the previous example program, and I have shown that the error has been recognized by the ON-EXIT group.

My last example is a program with a Main procedure and a subprocedure:

01  **free
02  ctl-opt main(Main) dftactgrp(*no) ;

03  dcl-s Number int(3) ;

04  dcl-proc Main ;
05    Number = 0 ;
06    DoDivision(Number) ;
07    dsply ('After subprocedure') ;

08  on-exit ;
09    dsply ('Main ON-EXIT') ;
10  end-proc ;

11  dcl-proc DoDivision ;
12    dcl-pi *n int(3) ;
13      SubNumber int(3) ;
14    end-pi ;
15    dcl-s ErrorHappened ind ;

16    SubNumber = SubNumber / SubNumber ;
17    dsply ('After subprocedure division') ;
18    return SubNumber ;

19  on-exit ErrorHappened ;
20    if (ErrorHappened) ;
21      dsply ('Error happened in subprocedure') ;
22    else ;
23      dsply ('Everything is OK in subprocedure') ;
24    endif ;
25  end-proc ;

Line 6: The Main procedure calls the subprocedure DoDivision.

Line 7: When control is returned from the subprocedure the DSPLY operation code is used to display message.

Lines 8 and 9: The ON-EXIT group in the Main procedure just displays a message to show it has been performed.

As I am calling the subprocedure just in this program I don't have to have a procedure protype definition.

Line 11: The DoDivision subprocedure starts here.

Lines 12 – 14: I need the procedure interface as I am passing and returning the Number variable, which I have called SubNumber in this subprocedure.

The rest of the subprocedure looks very similar to the Main procedure in my last example program, therefore, I am not going to explain it again.

After compiling I called the program and these were the messages I received:

DSPLY  Error happened in subprocedure
DSPLY  Main ON-EXIT

As the division failed the first message is from the ON-EXIT group in the subprocedure. As this is still an error situation when control was passed to the Main procedure it "jumped" straight into its ON-EXIT.

By contrast if I change the value I moved into Number to 1 the following messages were sent:

DSPLY  After subprocedure division    
DSPLY  Everything is OK in subprocedure
DSPLY  After subprocedure             
DSPLY  Main ON-EXIT    

I hope these examples give you pause to thought on how you might use the ON-EXIT groups to handle any errors that happened in the procedures and subprocedures.

 

This article was written for IBM i 7.5 TR1 and 7.4 TR7.

2 comments:

To prevent "comment spam" all comments are moderated.
Learn about this website's comments policy here.

Some people have reported that they cannot post a comment using certain computers and browsers. If this is you feel free to use the Contact Form to send me the comment and I will post it for you, please include the title of the post so I know which one to post the comment to.