saturnng/libChf/chf_hdlr.c

244 lines
7.8 KiB
C
Raw Normal View History

2022-03-21 11:05:59 +01:00
/* .+
.identifier : $Id: chf_hdlr.c,v 2.2 2001/01/25 12:12:46 cibrario Exp $
.context : CHF, Condition Handling Facility
.title : $RCSfile: chf_hdlr.c,v $, condition generation
.kind : C source
.author : Ivan Cibrario B.
.site : CSTV-CNR
.creation : 3-May-1996
.keywords : *
.description :
This module implements the CHF functions ChfPushHandler() and
ChfPopHandler()
.include : Chf.h
.notes :
$Log: chf_hdlr.c,v $
Revision 2.2 2001/01/25 12:12:46 cibrario
Added partial Win32 support (Windows CE only).
Revision 2.1 2000/05/26 14:45:04 cibrario
- Implemented StructuredHelper(), the structured condition handling
helper handler
- Updated ChfPushHandler() to push the structured condition handling
helper when new_handler is CHF_NULL_HANDLER
- unwind_context is now a sigjmp_buf, passed as argument directly,
that is, without additional address operators
- improved documentation of ChfPopHandler()
Revision 1.6 1997/01/15 13:44:39 cibrario
The function ChfPushHandler() has the new argument 'handler_context'.
Revision 1.1 1996/05/28 12:54:28 cibrario
Initial revision
.- */
#ifndef lint
static char rcs_id[] = "$Id: chf_hdlr.c,v 2.2 2001/01/25 12:12:46 cibrario Exp $";
#endif
#include <stdio.h>
#include <stdlib.h>
#ifndef _WIN32
# include <errno.h>
2022-03-21 11:05:59 +01:00
#endif
#include <setjmp.h>
#ifdef _WIN32
# include <windows.h>
# include <tchar.h>
2022-03-21 11:05:59 +01:00
#endif
#include "Chf.h"
#include "ChfPriv.h"
/* .+
.title : StructuredHelper
.kind : C function
.creation : 19-May-2000
.description :
This function is the structured condition handling helper of CHF.
It's automatically pushed into the condition handler stack by
ChfPushHandler() when its 'new_handler' argument is CHF_NULL_HANDLER,
and performs the following functions:
- if called during an ordinary signalling operation with a
CHF_FATAL condition, it requests the action CHF_UNWIND_KEEP
2022-03-21 11:05:59 +01:00
- if called when Chf is in any other state, or with a
severity less than CHF_FATAL, it requests the action CHF_RESIGNAL
2022-03-21 11:05:59 +01:00
The structured condition handling helper currently makes no use of
handler_context.
.call :
action = StructuredHelper(desc, state, context);
2022-03-21 11:05:59 +01:00
.input :
const ChfDescriptor *desc, condition descriptor
const ChfState state, current CHF state
2022-03-21 11:05:59 +01:00
.output :
ChfAction action, action requested by the handler
2022-03-21 11:05:59 +01:00
.status_codes :
none
2022-03-21 11:05:59 +01:00
.notes :
2.1, 19-May-2000, creation
.- */
static ChfAction StructuredHelper( const ChfDescriptor* desc, const ChfState state, ChfPointer handler_context )
2022-03-21 11:05:59 +01:00
{
ChfAction action;
const ChfDescriptor* d;
2022-03-21 11:05:59 +01:00
return ( ( state == CHF_SIGNALING && ChfGetSeverity( desc ) == CHF_FATAL ) ? CHF_UNWIND_KEEP : CHF_RESIGNAL );
2022-03-21 11:05:59 +01:00
}
/* .+
.title : ChfPushHandler
.kind : C function
.creation : 13-May-1996
.description :
This function pushes the new condition handler 'new_handler' with its
associated longjmp context pointed by 'unwind_context' into the handler
stack and returns CHF_S_OK to the caller. If 'new_handler' is
CHF_NULL_HANDLER, the special structured condition handling helper
'StructuredHelper()' is pushed instead.
Moreover, this function saves a copy of the pointer 'handler_context'; it
will be passed to 'new_handler' upon each subsequent activation, and
therefore can be used as a private handler context pointer. The user must
assure that the information pointed by 'handler_context', if any, will
remain valid until 'new_handler' is popped from the condition stack.
'handler_context' may be set to the special (null) value CHF_NULL_POINTER to
indicate that the handler hasn't any private context information.
2022-03-21 11:05:59 +01:00
If, in the future, the handler will request the CHF_UNWIND action, the
setjmp() function invocation that established 'unwind_context' will appear
to return again.
'unwind_context' can be the reserved (null) pointer CHF_NULL_CONTEXT; in
this case, if the handler will request the CHF_UNWIND_ACTION, the
application will be silently terminated calling ChfAbort() with abort code
CHF_ABORT_SILENT.
If some error occours during the execution, the function will generate
and immediately signal one of the conditions listed below and marked with
(*). The function will never return dorectly to the caller, since all
conditions are CHF_FATAL.
NOTE: This function calls ChfAbort() with abort code CHF_ABORT_INIT if
the CHF subsystem has not been initialized.
2022-03-21 11:05:59 +01:00
.call :
ChfPushHandler(new_handler, unwind_context);
2022-03-21 11:05:59 +01:00
.input :
ChfHandler new_handler, new condition handler
void *unwind_context, handler unwind context pointer
ChfPointer handler_context, private handler context pointer
2022-03-21 11:05:59 +01:00
.output :
void
2022-03-21 11:05:59 +01:00
.status_codes :
(*) CHF_F_BAD_STATE, bad CHF state for requested operation
(*) CHF_F_HDLR_STACK_FULL, the handler stack is full
2022-03-21 11:05:59 +01:00
.notes :
1.1, 13-May-1996, creation
1.6, 15-Jan-1997, update:
- added the argument 'handler_context'
- improved documentation
2.1, 19-May-2000, update:
- now using sigjmp_buf as unwind_context
- added StructuredHelper handling
.- */
void ChfPushHandler( /* Push a new handler into the stack */
ChfHandler new_handler, void* unwind_context, ChfPointer handler_context )
2022-03-21 11:05:59 +01:00
{
/* Make sure that CHF has been correctly initialized and is idle */
if ( chf_context.state == CHF_UNKNOWN )
ChfAbort( CHF_ABORT_INIT );
if ( chf_context.state != CHF_IDLE ) {
ChfCondition CHF_F_BAD_STATE, CHF_FATAL ChfEnd;
2022-03-21 11:05:59 +01:00
ChfSignal();
}
/* Check if the handler stack is full */
else if ( chf_context.handler_sp - chf_context.handler_stack >= chf_context.handler_stack_size ) {
ChfCondition CHF_F_HDLR_STACK_FULL, CHF_FATAL ChfEnd;
ChfSignal();
}
else {
chf_context.handler_sp->unwind_context = unwind_context;
chf_context.handler_sp->handler_context = handler_context;
chf_context.handler_sp->handler = ( ( new_handler == CHF_NULL_HANDLER ) ? StructuredHelper : new_handler );
chf_context.handler_sp++;
}
}
2022-03-21 11:05:59 +01:00
/* .+
.title : ChfPopHandler
.kind : C function
.creation : 13-May-1996
.description :
This function pops the topmost condition handler from the handler stack and
returns to the caller.
2022-03-21 11:05:59 +01:00
If some error occours during the execution, the function will generate
and immediately signal one of the conditions listed below and marked with
(*). The function will never return directly to the caller, since all
conditions are CHF_FATAL.
NOTE: This function calls ChfAbort() with abort code CHF_ABORT_INIT if
the CHF subsystem has not been initialized.
2022-03-21 11:05:59 +01:00
.call :
ChfPopHandler();
2022-03-21 11:05:59 +01:00
.input :
void
2022-03-21 11:05:59 +01:00
.output :
void
2022-03-21 11:05:59 +01:00
.status_codes :
CHF_F_BAD_STATE, bad CHF state for requested operation
CHF_F_HDLR_STACK_FULL, the handler stack is full
2022-03-21 11:05:59 +01:00
.notes :
1.1, 13-May-1996, creation
1.6, 15-Jan-1997, update:
- improved documentation
2.1, 19-May-2000, update:
- improved documentation
.- */
void ChfPopHandler( /* Pop a handler */
void )
2022-03-21 11:05:59 +01:00
{
/* Make sure that CHF has been correctly initialized and is idle */
if ( chf_context.state == CHF_UNKNOWN )
ChfAbort( CHF_ABORT_INIT );
2022-03-21 11:05:59 +01:00
if ( chf_context.state != CHF_IDLE ) {
ChfCondition CHF_F_BAD_STATE, CHF_FATAL ChfEnd;
2022-03-21 11:05:59 +01:00
ChfSignal();
}
2022-03-21 11:05:59 +01:00
/* Check if the handler stack is empty */
else if ( chf_context.handler_sp == chf_context.handler_stack ) {
ChfCondition CHF_F_HDLR_STACK_EMPTY, CHF_FATAL ChfEnd;
2022-03-21 11:05:59 +01:00
ChfSignal();
}
2022-03-21 11:05:59 +01:00
/* Discard the topmost condition handler */
else
--chf_context.handler_sp;
2022-03-21 11:05:59 +01:00
}