saturnng/libChf/chf_gen.c
2024-03-26 15:51:15 +01:00

165 lines
5.7 KiB
C

/* .+
.identifier : $Id: chf_gen.c,v 2.2 2001/01/25 12:10:22 cibrario Exp $
.context : CHF, Condition Handling Facility
.title : $RCSfile: chf_gen.c,v $, condition generation
.kind : C source
.author : Ivan Cibrario B.
.site : CSTV-CNR
.creation : 3-May-1996
.keywords : *
.description :
This module contains the condition generation function of CHF
.include : Chf.h
.notes :
$Log: chf_gen.c,v $
Revision 2.2 2001/01/25 12:10:22 cibrario
Added partial Win32 support (Windows CE only).
Revision 1.1 1996/05/28 12:53:59 cibrario
Initial revision
.- */
#ifndef lint
static char rcs_id[] = "$Id: chf_gen.c,v 2.2 2001/01/25 12:10:22 cibrario Exp $";
#endif
#include <stdio.h>
#include <stdlib.h>
#ifndef _WIN32
# include <errno.h>
#endif
#include <setjmp.h>
#include <stdarg.h>
#include <string.h>
#ifdef _WIN32
# include <windows.h>
# include <tchar.h>
#endif
#include "Chf.h"
#include "ChfPriv.h"
/* .+
.title : ChfGenerate
.kind : C function
.creation : 3-May-1996
.description :
This function generates a condition descriptor for the condition described
by 'module_id', 'file_name', 'line_number', 'condition_code' and 'severity',
and the partial message associated with it, specialized with the additional
arguments '...'; the new condition descriptor is put onto the top of the
condition stack.
If the condition stack is full, this function generates the condition
CHF_F_COND_STACK_FULL and immediately invokes ChfSignal() for the current
condition stack.
NOTE: This function calls the CHF function 'ChfAbort()' to
abort the application if either:
- CHF has not been initialized correctly (abort code CHF_ABORT_INIT)
- there is an overflow in the internal buffer used during the
generation of the partial message associated with the condition
(abort code CHF_ABORT_MSG_OVF)
- there was an attempt to generate a condition while the CHF condition
CHF_F_COND_STACK_FULL (condition stack full) was being signalled
(abort code CHF_ABORT_COND_STACK_OVF)
.call :
ChfGenerate(module_id, file_name, line_number,
condition_code, severity, ...);
.input :
const int module_id, module identifier
const char *file_name, file name
const int line_number, line number
const int condition_code, condition code
const ChfSeverity severity, severity
..., additional arguments
.output :
void
.status_codes :
(*) CHF_F_COND_STACK_FULL, the condition stack is full
.notes :
1.1, 3-May-1996, creation
.- */
void ChfGenerate( /* Generate a condition into the stack */
const int module_id, const ChfChar* file_name, const int line_number, const int condition_code,
const ChfSeverity severity, ... )
{
ChfDescriptor* new_descriptor;
va_list aux_arg;
/* Check that CHF has been correctly initialized */
if ( chf_context.state == CHF_UNKNOWN )
ChfAbort( CHF_ABORT_INIT );
/* Prepare the additional arguments list */
va_start( aux_arg, severity );
if ( ( new_descriptor = chf_context.condition_sp ) - chf_context.condition_stack >= chf_context.condition_stack_size ) {
/* The condition stack is full;
generate the CHF_F_COND_STACK_FULL condition and signal it immediately,
using the last available slot of the stack, if it's still empty,
otherwise abort the application.
*/
if ( new_descriptor - chf_context.condition_stack == chf_context.condition_stack_size ) {
new_descriptor->module_id = CHF_MODULE_ID;
new_descriptor->condition_code = CHF_F_COND_STACK_FULL;
new_descriptor->severity = CHF_FATAL;
new_descriptor->line_number = CHF_UNKNOWN_LINE_NUMBER;
new_descriptor->file_name = CHF_UNKNOWN_FILE_NAME;
ChfStrncpy( new_descriptor->message,
ChfGetMessage( CHF_MODULE_ID, CHF_F_COND_STACK_FULL, ChfText( "Condition stack is full" ) ),
CHF_MAX_MESSAGE_LENGTH - 1 );
new_descriptor->message[ CHF_MAX_MESSAGE_LENGTH - 1 ] = '\0';
new_descriptor->next = CHF_NULL_DESCRIPTOR;
chf_context.condition_sp++;
ChfSignal();
}
else
ChfAbort( CHF_ABORT_COND_STACK_OVF );
}
else {
ChfChar def_message[ CHF_DEF_MESSAGE_LENGTH ];
ChfChar tmp_message[ CHF_TMP_MESSAGE_LENGTH ];
new_descriptor->module_id = module_id;
new_descriptor->condition_code = condition_code;
new_descriptor->severity = severity;
new_descriptor->line_number = line_number;
new_descriptor->file_name = file_name;
/* Generate the default message */
ChfSprintf( def_message, CHF_DEF_PARTIAL_MSG_FMT, condition_code );
/* Generate the partial message associated with the condition using a
temporary area
*/
if ( ChfVsprintf( tmp_message, ChfGetMessage( module_id, condition_code, def_message ), aux_arg ) >= CHF_TMP_MESSAGE_LENGTH )
ChfAbort( CHF_ABORT_MSG_OVF );
/* Copy the message into the condition descriptor */
ChfStrncpy( new_descriptor->message, tmp_message, CHF_MAX_MESSAGE_LENGTH - 1 );
new_descriptor->message[ CHF_MAX_MESSAGE_LENGTH - 1 ] = '\0';
/* Link the new descriptor with the current descriptor list, if it
isn't the first descriptor of the list
*/
new_descriptor->next = ( new_descriptor == chf_context.condition_base ) ? CHF_NULL_DESCRIPTOR : new_descriptor - 1;
chf_context.condition_sp++;
}
}