ILE C/C++ Programmer's Guide
ILE condition handlers allow you to register one or more condition
handlers at run time. To register an ILE condition handler, use the
Register ILE Condition Handler (CEEHDLR) bindable API. Include the
<lecond.h> header file in your source code when using
these APIs. ILE condition handlers may be unregistered by calling the
Unregister ILE Condition Handler (CEEHDLU) bindable API.
Condition handlers are exception handlers that are registered at run time
by using the Register ILE Condition Handler (CEEHDLR) bindable API.
They are used to handle, percolate or promote exceptions. The
exceptions are presented to the condition handlers in the form of an ILE
condition.
If you want to have a consistent mechanism of condition handling across
several ILE languages (or for scoping exception handling to a call stack
entry), use the ILE bindable API CEEHDLR. Unlike the signal handler
,which is scoped to the activation group, CEEHDLR is scoped to the function
that calls it.
The ILE condition handler uses ILE conditions to allow greater cross-system
consistency. An ILE condition is a system-independent representation of
an error condition in an HLL.
The following example shows the source for a program MYPGM:
Figure 174. T1520XH5 -- ILE C Source to Use ILE Condition Handlers -- main()
#include <lecond.h>
#include <stdio.h>
void my_handler(_FEEDBACK *cond, _POINTER *token, _INT4 *rc, _FEEDBACK *new );
void main_handler(_FEEDBACK *cond, _POINTER *token, _INT4 *rc, _FEEDBACK *new );
void fred(void)
{
_HDLR_ENTRY hdlr=my_handler;
char *p = NULL;
CEEHDLR(&hdlr, NULL,NULL);
*p = 'x'; /* exception */
CEEHDLU(&hdlr,NULL);
}
int main(void)
{
_HDLR_ENTRY hdlr=main_handler;
CEEHDLR(&hdlr,NULL,NULL);
fred();
}
|
In the example MYPGM:
- The procedure main() registers the condition handler
main_handler.
- The procedure main() calls the function fred() which
registers the condition handler my_handler.
- Function fred() gets an exception causing
my_handler to get control, followed by
main_handler.
The main() function is a control boundary. The exception
is considered unhandled, so a function check is sent to function
fred(). Handlers my_handler and
main_handler are called again, this time for the function
check. Neither of them handle the function check, so the program ends
abnormally and a CEE9901 message is sent to the caller of the
main() function.
The following example shows the source for the service program HANDLERS:
Figure 175. T1520XH6 -- ILE C Source to Use ILE Condition Handlers -- Service Program
#include <signal.h>
#include <stdio.h>
#include <lecond.h>
/* HANDLERS *SRVPGM (*CALLER) */
void my_handler(_FEEDBACK *cond, _POINTER *token, _INT4 *rc, _FEEDBACK *new)
{
return;
}
void main_handler(_FEEDBACK *cond, _POINTER *token, _INT4 *rc, _FEEDBACK *new)
{
printf("In main_handler\n");
}
|
The following example shows how to use a condition handler to handle an
exception. In the example:
- ILE condition handler cond_hdlr is registered in the
main() function using CEEHDLR.
- An MCH1211 (divide-by-zero) exception then occurs. Handler
cond_hdlr is called and it indicates that the exception should
be handled.
- Control then resumes in the main() function.
The following steps create and run the source in Figure 176.
- To create the program T1520IC6, enter:
CRTBNDC PGM(MYLIB/T1520IC6) SRCFILE(QCPPLE/QACSRC)
- To run the program T1520IC6, enter:
CALL PGM(MYLIB/T1520IC6)
The output is:
+--------------------------------------------------------------------------------+
| condition was raised: Facility_ID = MCH, MsgNo = 0x1211 |
| The condition was handled. |
| Press ENTER to end terminal session. |
+--------------------------------------------------------------------------------+
Figure 176. T1520IC6 -- ILE C Source to Use ILE Condition Handlers
/* This program uses the ILE bindable API CEEHDLR to handle a */
/* condition. */
#include <stdio.h>
#include <stdlib.h>
#include <leawi.h>
/* A condition handler registered by a call to CEEHDLR in main(). */
void cond_hdlr( _FEEDBACK *cond, _POINTER *token, _INT4 *rc, _FEEDBACK *new )
{
*rc = CEE_HDLR_RESUME; /* handle the condition */
printf("condition was raised: Facility_ID = %.3s, MsgNo = 0x%4.4x\n",
cond->Facility_ID, cond->MsgNo);
}
int main(void)
{
_HDLR_ENTRY hdlr = cond_hdlr;
_FEEDBACK fc;
int x,y;
int zero = 0;
/* Register the condition handler. */
CEEHDLR(&hdlr, NULL, &fc);
if (fc.MsgNo != CEE0000)
{
printf("Failed to register the condition handler\n");
exit(88);
}
/* Cause a divide by zero condition. */
x = y / zero;
/* The code resumes here after the condition has been handled. */
printf("The condition was handled.\n");
}
|
In this example:
- The bindable API CEEHDLR registers the main_hdlr in function
main().
- The bindable API CEEHDLR registers the fred_hdlr in function
fred().
- An MCH1211 (divide-by-zero) exception occurs.
- Handler fred_hdlr is called to test if the exception is an
MCH1211.
- The result code in the condition handler is set to percolate to the next
condition handler.
- Handler fred_hdlr returns without handling the exception,
causing main_hdlr to be called.
- The user-supplied token is updated to the value '1' and the
result code is set to handle the exception.
- Handler main_hdlr returns, and the exception is
handled.
- Control resumes in fred() following the statement that caused
the divide-by-zero.
This example uses the source shown in Figure 177.
- To create the program T1520IC7, enter:
CRTBNDC PGM(MYLIB/T1520IC7) SRCFILE(QCPPLE/QACSRC)
- To run the program T1520IC7, enter:
CALL PGM(MYLIB/T1520IC7)
The output is:
+--------------------------------------------------------------------------------+
|in fred_hdlr, percolate exception. |
|in main hdlr: Facility_ID = MCH, MsgNo = 0x1211 |
|Resume here because resume cursor not moved and main_hdlr handled the exception.|
|A condition was percolated from fred() to main() and was then handled. |
|Press ENTER to end terminal session. |
+--------------------------------------------------------------------------------+
Figure 177. T1520IC7 -- ILE C Source to Percolate a Message to Handle a Condition
/* This program uses the ILE bindable API CEEHDLR to enable handlers */
/* that percolate and handle a condition. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <leawi.h>
/* A condition handler registered by a call to CEEHDLR in fred(). */
void fred_hdlr( _FEEDBACK *cond, _POINTER *token, _INT4 *rc, _FEEDBACK *new )
{
if (!memcmp(cond->Facility_ID, "MCH", 3) && cond->MsgNo == 0x1211)
{
*rc = CEE_HDLR_PERC; /* ... let it percolate to main ... */
printf("in fred_hdlr, percolate exception.\n");
}
else
{
*rc = CEE_HDLR_RESUME; /* ... otherwise handle it. */
printf("in fred_hdlr, handle exception.\n");
}
}
/* A condition handler registered by a call to CEEHDLR in main(). */
void main_hdlr( _FEEDBACK *cond, _POINTER *token, _INT4 *rc, _FEEDBACK *new )
{
printf("in main hdlr: Facility_ID = %.3s, MsgNo = 0x%4.4x\n",
cond->Facility_ID, cond->MsgNo);
**(_INT4 **)token = 1; /* Update the user's token. */
*rc = CEE_HDLR_RESUME; /* Handle the condition */
}
int fred(void)
{
_HDLR_ENTRY hdlr = fred_hdlr;
_FEEDBACK fc;
int x,y, zero = 0;
/* Register the handler without a token. */
CEEHDLR(&hdlr, NULL, &fc);
if (fc.MsgNo != CEE0000)
{
printf("Failed to register the condition handler\n");
exit(88);
}
/* Cause a divide by zero condition. */
x = y / zero;
printf("Resume here because resume cursor not moved and main_hdlr"
" handled the exception\n");
}
int main(void)
{
_HDLR_ENTRY hdlr = main_hdlr;
_FEEDBACK fc;
volatile _INT4 token=0, *tokenp = &token;
/* Register the handler with a token of type _INT4. */
CEEHDLR(&hdlr, (_POINTER *)&tokenp, &fc);
if (fc.MsgNo != CEE0000)
{
printf("Failed to register the condition handler\n");
exit(99);
}
fred();
/* See if the condition handler for main() updated the token. */
if (*tokenp == 1)
printf("A condition was percolated from fred() to main() and"
" was then handled.\n");
}
|
In the following example:
- In main(), the bindable API CEEHDLR registers the
main_hdlr.
- In fred(), the bindable API CEEHDLR registers the
fred_hdlr.
- An MCH1211 (divide-by-zero) exception occurs and the handler
fred_hdlr is called.
- The handler fred_hdlr moves the resume cursor to the resume point in
the main() function using the bindable API CEEMRCR.
- The handler fred_hdlr builds a condition token for CEE9902,
and the result code is set to promote.
- The handler fred_hdlr returns, and the original MCH1211 is
promoted to a CEE9902.
- The handler main_hdlr is called because of the CEE9902
exception and the result code is set to handle the condition.
- The handler main_hdlr returns, and the CEE9902 is
handled.
- Control resumes in the statement following the call to fred()
in main()
The source code in program T1520IC8 is shown in Figure 178.
- To create the program T1520IC8, , enter:
CRTBNDC PGM(MYLIB/T1520IC8) SRCFILE(QCPPLE/QACSRC)
- To run the program T1520IC8, enter:
CALL PGM(MYLIB/T1520IC8)
The output is status information messages:
+--------------------------------------------------------------------------------+
|in fred_hdlr: moving resumes. Facility_ID = MCH, MsgNo = 0x1211 |
|promoting condition.... |
|A condition was promoted from MCH1211 to CEE9902 by fred() and was handled by |
| the condition handler enabled in main(). |
|Press ENTER to end terminal session. |
+--------------------------------------------------------------------------------+
Figure 178. T1520IC8 -- ILE C Source to Promote a Message to Handle a Condition
/* This program uses the ILE bindable API CEEHDLR to promote a */
/* divide by zero condition to a CEE9902. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <leawi.h>
/* A condition handler registered by a call to CEEHDLR in fred(). */
void fred_hdlr( _FEEDBACK *cond, _POINTER *token, _INT4 *rc, _FEEDBACK *new )
{
_INT4 type=1;
CEEMRCR(&type,NULL); /* Move the resume cursor to the resume point */
/* in main(). */
/* If its a divide by zero error ... */
printf("in fred_hdlr: moving resumes. ");
printf("Facility_ID = %.3s, MsgNo = 0x%4.4x\n",
cond->Facility_ID, cond->MsgNo);
if (!memcmp(cond->Facility_ID, "MCH", 3) && cond->MsgNo == 0x1211)
{
*rc = CEE_HDLR_PROM; /*... Promote the condition to unexpected error.*/
*new = *cond;
memcpy(new->Facility_ID, "CEE", 3);
new->MsgNo = 9902;
printf("promoting condition....\n");
}
else
{
*rc = CEE_HDLR_PERC; /*...Otherwise,Percolate to the next handler. */
printf("percolating condition....\n");
}
}
/* A condition handler registered by a call to CEEHDLR in main(). */
void main_hdlr( _FEEDBACK *cond, _POINTER *token, _INT4 *rc, _FEEDBACK *new )
{
if (!memcmp(cond->Facility_ID,"CEE",3) && cond->MsgNo == 9902;)
**(_INT4 **)token = 1; /* Got the promoted CEE9902. */
else
**(_INT4 **)token = 2; /* It is not a CEE9902. */
*rc = CEE_HDLR_RESUME; /* Handle the condition. */
}
int fred(void)
{
_HDLR_ENTRY hdlr = fred_hdlr;
_FEEDBACK fc;
int x,y, zero = 0;
/* Register the handler without a token. */
CEEHDLR(&hdlr, NULL, &fc);
if (fc.MsgNo != CEE0000)
{
printf("Failed to register the condition handler\n");
exit(88);
}
/* Cause a divide by zero condition. */
x = y / zero;
/* This is not the resume point because of the call to CEEMRCR in */
/* fred_hdlr. */
{
printf("This is not the resume point: should not get here\n");
}
}
int main(void)
{
_HDLR_ENTRY hdlr = main_hdlr;
_FEEDBACK fc;
volatile _INT4 token=0, *tokenp = &token;
/* Register the handler with a token of type _INT4. */
CEEHDLR(&hdlr, (_POINTER *)&tokenp, &fc);
if (fc.MsgNo != CEE0000)
{
printf("Failed to register the condition handler\n");
exit(99);
}
fred();
/* See if the condition handler for main() received the promoted */
/* condition. */
if (*tokenp == 1)
printf("A condition was promoted from MCH1211 to CEE9902 by "
"fred() and was handled by the condition handler enabled "
"in main().\n");
}
|
[ Top of Page | Previous Page | Next Page | Table of Contents ]
(C) Copyright IBM Corporation 1992, 2005. All Rights Reserved.