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.
Spectacular article Simon. Thank you.
ReplyDelete