Signaling and handling a condition in a C/C++ routine
The next program shows how a user-written condition handler gains
control for a condition that was signaled using CEESGL, and calls
CEEGQDT to access a data structure that was set up in the signaling
routine. The CEEMRCR callable service resets the resume cursor, and
execution resumes at the new point.
/*Module/File Name: EDCSIGH */
/**********************************************************************/
/* This example shows how several of the Language Environment */
/* condition management callable services are used. The services */
/* shown are: */
/* CEEHDLR -- register a user condition handler */
/* CEESGL -- signal a condition to the condition manager */
/* CEEGQDT -- get the q_data_token */
/* CEEMRCR -- move the resume cursor */
/* */
/* The example also shows how to directly construct a condition token */
/* and provides a sample user condition handler. */
/**********************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <leawi.h>
#include <ceeedcct.h>
void b(void);
#ifdef __cplusplus
extern "C" {
#endif
void handler(_FEEDBACK *,_INT4 *,_INT4 *,_FEEDBACK *);
#ifdef __cplusplus
}
#endif
typedef struct { /* condition info structure */
int error_value;
char err_msg[80];
int retcode;
} info_struct;
int main(void) {
printf("In main program\n");
b();
/* CEEMRCR should put the resume cursor at this point */
printf("Finished\n");
}
void b(void) {
_FEEDBACK fc,condtok;
_ENTRY routine;
_INT4 token,qdata;
info_struct *info;
_INT2 c_1,c_2,cond_case,sev,control;
_CHAR3 facid;
_INT4 isi;
printf("In routine b\n");
token = 99;
routine.address = (_POINTER)&handler;
routine.nesting = NULL;
/* register the condition handler: */
CEEHDLR(&routine,&token,&fc);
if ( _FBCHECK ( fc , CEE000 ) != 0 ) {
printf("CEEHDLR failed with message number %d\n",
fc.tok_msgno);
exit(2999);
}
/* build the condition token */
c_1 = 1;
c_2 = 99;
cond_case = 1;
sev = 1;
control = 0;
memcpy(facid,"ZZZ",3);
isi = 0;
CEENCOD(&c_1,&c_2,&cond_case,&sev,&control,
facid,&isi,&condtok,&fc);
if ( _FBCHECK ( fc , CEE000 ) != 0 ) {
printf("CEENCOD failed with message number %d\n",
fc.tok_msgno);
exit(2999);
}
/* set up the condition info structure */
info = (info_struct *)malloc(sizeof(info_struct));
if (info == NULL) {
printf("error allocating info_struct\n");
exit(2399);
}
memset(info->err_msg,' ',79);
info->err_msg[79] = '\0';
info->error_value = 86;
memcpy(info->err_msg,"Test message",12);
info->retcode = 99;
/* set qdata to be the condition info structure */
qdata = (int)info;
/* signal the condition */
CEESGL(&condtok,&qdata,NULL);
printf("Failed: handler should have moved resume cursor past this\n");
}
/**********************************************************************/
/* User condition handler */
/**********************************************************************/
void handler(_FEEDBACK *fc, _INT4 *token, _INT4 *result,
_FEEDBACK *newfc) {
_FEEDBACK cursorfc, orig_fc;
_INT4 type;
_INT4 qdata;
/* if the condition is not mine (ZZZ facid) then percolate */
if (memcmp(fc->tok_facid,"ZZZ",3) != 0) {
*result = 20;
return;
}
printf("%d is handling the condition for Control\n",*token);
/* get the q_data_token */
CEEGQDT(fc,&qdata,NULL);
/* look at the q_data_token and print out a message if the */
/* error_value was 86 */
if (((info_struct *)qdata)->error_value == 86)
printf("%.80s\n",((info_struct*)qdata)->err_msg);
/* move the resume cursor to the caller of the routine */
/* that registered this handler */
type = 1;
CEEMRCR(&type,&cursorfc);
if ( _FBCHECK ( cursorfc , CEE000 ) != 0 ) {
printf("CEEMRCR failed with message number %d\n",
cursorfc.tok_msgno);
exit(2999);
}
/* mark the condition as handled and return */
printf("Condition handled\n");
*result = 10;
return;
}