\input texinfo @c -*-texinfo-*- @c $Id: chf.texi,v 2.2 2001/01/25 12:06:29 cibrario Exp $ @c %**start of header @setfilename chf.info @settitle Chf library (libChf r2.2) Documentation @setchapternewpage on @iftex @afourpaper @end iftex @c %**end of header @ifinfo This manual documents the Condition Handling Facility library (libChf r2.2). The Chf library provides a centralized, unified method of generating and signaling exceptional conditions, establishing exception handlers, and printing status and error messages. @end ifinfo @titlepage @title CHF library Documentation @subtitle Condition Handling Facility library @subtitle (libChf r2.2) @author Ivan Cibrario B. @end titlepage @node Top, Overview, (dir), (dir) @ifinfo This manual describes the Condition Handling Facility library, and applies to its release 2.2. @end ifinfo @menu * Overview:: * Initialization and exit:: * Condition generation and signal:: * General condition handling:: * Structured condition handling:: * Chf conditions:: * Message retrieval:: * Multithreading support:: * Other useful macro definitions:: * Other useful functions:: * Changes since release 1:: * Changes since release 2.1:: * Function Index:: * Data Type Index:: * Concept Index:: @c @detailmenu --- The Detailed Node Listing --- Initialization and exit * ChfInit():: * ChfMsgcatInit():: * ChfStaticInit():: * ChfWin32Init():: * ChfExit():: * ChfAbort():: * Library header:: Condition generation and signal * Generating a condition:: * Signaling a condition:: Generating a condition * ChfCondition:: * ChfEnd:: * ChfSeverity:: * ChfErrnoCondition:: Signaling a condition * ChfSignal():: Condition handling * Condition handlers:: * Condition descriptors:: * Condition handling state:: * Handler actions:: * Default handler:: Condition handlers * ChfHandler:: * ChfPushHandler():: * ChfPopHandler():: Structured condition handling * Syntax of structured condition handlers:: * Chf behavior during structured condition handling:: Chf behavior during structured condition handling * ChfTry:: * ChfCatch:: * ChfEndTry:: Message retrieval * Retrieving a message:: * Reserved module identifiers:: * Defining a new message retrieval subsystem:: Retrieving a message * ChfGetMessage():: * ChfBuildMessage():: @c @end detailmenu @end menu @node Overview, Initialization and exit, Top, Top @chapter Overview @cindex Overview @cindex Win32 Support The Condition Handling facility library provides a centralized, unified method of generating and signaling exceptional conditions. This method can be used either in conjunction with, or in alternative to, the traditional style of handling error conditions by returning distinguished error values when an error occurs in a procedure, and checking for these values after each procedure invocation. It serves many different purposes: @itemize @bullet @item It helps to gather and make available as much information as possible when an error occurs, such as which source module detected it, its severity, and any other ancillary information the user may find useful. @item It provides an unified method to log and print error messages, and to internationalize applications. @item By means of condition handlers, it gives the user a convenient way to implement global exception recovery actions in an application. @item It may improve the readability of the source code, because less explicit checks for error conditions are required. @end itemize Since release @code{2.2}, the Chf library also supports Unicode-based Win32 systems, notably Windows CE. Implementation details of the Win32 version of the library will be discussed in the documentation, and will be highlighted by the @strong{Win32} keyword. Moreover, the following general notes apply: @itemize @bullet @item All library functions, when compiled for Win32, handle Unicode character strings (array of @code{TCHAR}) instead of ASCII strings (array of @code{char}); this change is transparent and the documentation does not reflect it. @item Library functions @code{sigsetjmp()} and @code{siglongjmp()} are not supported; accordingly, they are replaced by @code{setjmp()} and @code{longjmp()}. The non-local control transfer context buffer, @code{sigjmp_buf} is also replaced by @code{jmp_buf}; this change is transparent and the documentation does not reflect it. @item The reentrant flavor of the Chf library is not yet supported. Multithreaded application must serialize Chf accesses themselves. @item The @code{ChfErrnoCondition} macro is not supported, and has no effect. @item The default condition handler does not display the condition message on the standard error stream. @item The @code{CHF_ABORT} initialization flag is not fully supported; when used, the Chf library invokes @code{exit(EXIT_FAILURE)} instead of @code{abort()} (not supported by Win32) to abort the application. @end itemize The following terms will be used often throughout this document: @table @code @item Exception @cindex Exception An @dfn{exception} is an event that changes the normal flow of instruction execution, and is usually caused by an error condition. Any procedure can generate an exception using the @code{ChfGenerate} macro, and then raise or signal it using the @code{ChfSignal()} function call. @item Condition @cindex Condition An informational state which exists when an exception occurs, and encloses information about the exception itself. The term @dfn{condition} is preferred, since the term exception usually implies an error. @item Condition handling @cindex Condition handling When a condition is detected during the execution of a procedure, the procedure can signal the condition. The hierarchy of currently active condition handlers is then permitted to respond to the condition; the procedure response is called @dfn{condition handling}. The condition handlers are themselves procedures and they are called with the usual calling conventions; the only exception is that, in the current release of the Chf library, they cannot establish condition handlers of their own. A procedure can establish a condition handler using the function @code{ChfPushHandler()}, that pushes a new condition handler on top of a LIFO handler stack; the condition handler stays active until a matching call to @code{ChfPopHandler()}, that pops the topmost handler from the handler stack is executed, or until an execution stack unwind occurs. Another way to implicitly establishing and removing condition handlers is to use the structured condition handling macros. @xref{Structured condition handling}, for more information. @end table @node Initialization and exit, Condition generation and signal, Overview, Top @chapter Initialization and exit @cindex Initialization and exit @cindex Initialization @cindex Exit Before using any function of the Chf library, it must be correctly initialized. Since the library has a generic interface towards the message retrieval subsystem (@pxref{Message retrieval}), more than one initialization function exist, one each for every message retrieval subsystem the library supports, plus one custom initialization function to use if a custom message retrieval subsystem is used. After initialization, the library accesses the message retrieval subsystem transparently, and its peculiarities are no longer visible to the users. All initialization functions, when successful, register a default condition handler. @xref{Default handler}. Moreover, each module using the Chf library must include the header file @code{Chf.h} and provide some basic definitions. @xref{Library header}. @menu * ChfInit():: * ChfMsgcatInit():: * ChfStaticInit():: * ChfWin32Init():: * ChfExit():: * ChfAbort():: * Library header:: @end menu @node ChfInit(), ChfMsgcatInit(), Initialization and exit, Initialization and exit @section ChfInit() @cindex Initialization @deftypefn Function int ChfInit (const char *app_name, const ChfOptions options, void *mrs_data, ChfMrsGet mrs_get, ChfMrsExit mrs_exit, const int condition_stack_size, const int handler_stack_size, const int exit_code) This function initializes the Chf library using a custom message retrieval subsystem, and returns to the caller a condition code; that code will be either @code{CHF_S_OK} if the initialization was successful, or one of the other values listed below. Arguments: @table @code @item app_name is the name of the application. It can be used by condition handlers to print out error messages. @item options is the bitwise or of the following option identifiers: @table @code @item CHF_DEFAULT Represents the default value for all options. @item CHF_ABORT If this flag is set, the Chf library will use @code{abort()} instead of either @code{exit(exit_code)} or @code{pthread_exit(exit_code)} to abort the application when an unrecoverable exception occurs. This forces a core dump that may be useful for debugging purposes. @strong{Win32:} This flag is not fully supported; the Chf library invokes @code{exit(EXIT_FAILURE)} instead of @code{abort()} (not supported by Win32) to abort the application. @end table @item mrs_data Private data pointer for the custom message retrieval subsystem. @item mrs_get Message retrieval subsystem's 'Get Message' function. @item mrs_exit Message retrieval subsystem's 'Exit' function. @item condition_stack_size Size of the condition stack. This value determines the maximum number of pending conditions, i.e. conditions that have been generated but have not been signaled yet. A condition that is being signaled is still pending until the signaling sequence completes. @item handler_stack_size Size of the handler stack. This value determines the maximum number of active condition handlers the application can have. A condition handler is activated when a @code{ChfPushHandler()} is executed for it, and it is deactivated when the corresponding @code{ChfPopHandler()} completes. In addition, each execution of the @code{ChfTry} macro also pushes a condition handler; the handler is removed when @code{ChfEndTry} is executed. @item exit_code This is the exit code the Chf library will use to exit either the application or the offending thread when an unrecoverable exception occurs. @end table Return values: @table @code @item CHF_S_OK The Chf library has been successfully initialized. @item CHF_F_MALLOC Dynamic memory allocation failed during initialization. @end table Notes: @itemize @bullet @item It's necessary to invoke successfully @code{ChfInit()}, either directly or indirectly, through another Chf initialization function, before using any other Chf function; otherwise, they will either fail and abort the application (when multithreading support is not enabled), or have unpredictable results (when multithreading support is enabled). @item This function will call @code{ChfAbort()} with abort code @code{CHF_ABORT_DUP_INIT} if the Chf library has already been initialized before. Notice that when multithreading support is enabled, @code{ChfInit()} must be invoked only once before starting multithreaded operation. @end itemize @end deftypefn @node ChfMsgcatInit(), ChfStaticInit(), ChfInit(), Initialization and exit @section ChfMsgcatInit() @cindex Initialization @cindex Internationalization @deftypefn Function int ChfMsgcatInit (const char *app_name, const ChfOptions options, const char *msgcat_name, const int condition_stack_size, const int handler_stack_size, const int exit_code) This function initializes the Chf library and activates the message retrieval subsystem based on @code{catgets()}, offering support for text-based internationalized applications. The argument @code{msgcat_name} is the name of the application/locale specific message catalog to be used to retrieve the messages. The other arguments have the meaning already described for @code{ChfInit()}, @xref{ChfInit()}. @strong{Win32:} This function is not supported and always returns @code{CHF_F_NOT_AVAILABLE}. Return values: @table @code @item CHF_S_OK The Chf library has been successfully initialized. @item CHF_F_SETLOCALE the @code{setlocale()} function has failed during initialization. @item CHF_F_CATOPEN the @code{catopen()} function has failed and therefore the message catalog was not opened. @item CHF_F_MALLOC Dynamic memory allocation failed during initialization. @item CHF_F_NOT_AVAILABLE Function not available on current platform. @end table Notes: @itemize @bullet @item It's necessary to invoke successfully either @code{ChfMsgcatInit()}, or another Chf initialization function described in this chapter, before using any other Chf function. @item This function will call @code{ChfAbort()} with abort code @code{CHF_ABORT_DUP_INIT} if the Chf library has already been initialized before. @end itemize @end deftypefn @node ChfStaticInit(), ChfWin32Init(), ChfMsgcatInit(), Initialization and exit @section ChfStaticInit() @cindex Initialization @deftypefn Function int ChfStaticInit (const char *app_name, const ChfOptions options, const ChfTable *table, const size_t table_size, const int condition_stack_size, const int handler_stack_size, const int exit_code) This function initializes the Chf library and activates the static message retrieval subsystem using the message table @code{table}, of @code{table_size} elements. This is the simplest message retrieval subsystem currently supported, and supports applications that must work with minimal operating system assistance. Return values: @table @code @item CHF_S_OK The Chf library has been successfully initialized. @item CHF_F_MALLOC Dynamic memory allocation failed during initialization. @end table Notes: @itemize @bullet @item It's necessary to invoke successfully either @code{ChfStaticInit()}, or another Chf initialization function described in this section, before using any other Chf function. @item This function will call @code{ChfAbort()} with abort code @code{CHF_ABORT_DUP_INIT} if the Chf library has already been initialized before. @end itemize @end deftypefn @deftp {Data type} ChfTable @cindex Standalone message table This data type is a structure representing an element of a standalone message table, to be used with the static message retrieval subsystem. Each table element associates a pair (@code{module_id}, @code{code}) with a message fragment or template. It has the following fields: @table @code @item int module The module identifier of the message fragment to be defined. @item int code The condition code of the message fragment to be defined. @item char *msg_template The message fragment or template associated with (@code{module_id}, @code{code}). @end table @end deftp @node ChfWin32Init(), ChfExit(), ChfStaticInit(), Initialization and exit @section ChfWin32Init() @cindex Initialization @cindex Internationalization @deftypefn Function int ChfWin32Init (const char *app_name, const ChfOptions options, HINSTANCE instance, const int condition_stack_size, const int handler_stack_size, const int exit_code) This function initializes the Chf library and activates the message retrieval subsystem based on the Win32 function @code{LoadString()}, offering limited support for Win32 internationalized applications. This function does not support message sets, so the linear message id passed to it is made by @code{module_id*1000 + condition_code}. The @code{instance} argument is the handle of the calling application instance; it will be used as an argument to @code{LoadString()}. All other arguments have the meaning already described for @code{ChfInit()}, @xref{ChfInit()}. @strong{Win32:} This function is supported on Win32 only, and always returns @code{CHF_F_NOT_AVAILABLE} when invoked on Unix platforms. Notice also that on Win32 the @code{ChfAbort()} function will be able to print out the abort message only if Chf has been initialized correctly and the @code{GetActiveWindow()} function yields a valid window handle when @code{ChfAbort()} is invoked. Return values: @table @code @item CHF_S_OK The Chf library has been successfully initialized. @item CHF_F_MALLOC Dynamic memory allocation failed during initialization. @item CHF_F_NOT_AVAILABLE Function not available on current platform. @end table Notes: @itemize @bullet @item It's necessary to invoke successfully either @code{ChfWin32Init()}, or another Chf initialization function described in this chapter, before using any other Chf function. @item This function will call @code{ChfAbort()} with abort code @code{CHF_ABORT_DUP_INIT} if the Chf library has already been initialized before. @end itemize @end deftypefn @node ChfExit(), ChfAbort(), ChfWin32Init(), Initialization and exit @section ChfExit() @cindex Exit @deftypefn Function void ChfExit (void) This function shuts down the Chf library and returns nothing to the caller; after calling @code{ChfExit()} the application can continue, but any subsequent call to other Chf functions, except to the initialization functions, will either abort the application using @code{ChfAbort()} with abort code @code{CHF_ABORT_INIT} (when multithreading support is not enabled) or have unpredictable results (when multithreading support is enabled). Notes: @itemize @bullet @item This function will call @code{ChfAbort()} with abort code @code{CHF_ABORT_INIT} if Chf hasn't been initialized yet. @item When multithreading support is enabled, it is responsibility of the application designer to ensure that no other Chf functions, except initialization functions, will be called after this function has been. @end itemize @end deftypefn @node ChfAbort(), Library header, ChfExit(), Initialization and exit @section ChfAbort() @cindex Abort @deftypefn Function void ChfAbort (const int abort_code) This function prints the message associated with @code{abort_code} and then immediately aborts either the application or the invoking thread. The abort is performed either: @itemize @bullet @item using @code{abort()} if either Chf has not been correctly initialized yet, or the Chf option flag @code{CHF_ABORT} has been set during initialization. Since this is mainly intended to be a debugging aid, @code{abort()} is used whether or not multithreading support is enabled. @strong{Win32:} The @code{CHF_ABORT} flag is not fully supported; when this flag is set the Chf library invokes @code{exit(EXIT_FAILURE)} instead of @code{abort()} (not supported by Win32) to abort the application. @item using either @code{exit(exit_code)} or @code{pthread_exit(exit_code)} if the above mentioned flag is clear. The former function is used when multithreading support is not enabled, the latter when it is. The argument @code{exit_code} is the value of the @code{exit_code} argument given to the Chf initialization function. @end itemize The following abort messages are currently defined: @table @code @item "Not initialized" The Chf library has not been correctly initialized. @item "Temporary message buffer overflow" The temporary message buffer used by Chf to combine the additional condition arguments with the message template was overflowed. Shorten the message. @item "Invalid action from last chance handler" The condition handler registered first, that usually is the default condition handler, has returned an invalid action code. @item "Already initialized" One of the Chf initialization functions was called when Chf was already initialized. @item "Unwind request while unwinding" A condition handler has requested an unwind action when Chf was already unwinding. This is not allowed. @item "Improperly handled condition" No condition handlers were able to properly handle the current condition group. This should not occur if the default condition handler is active as the last chance handler. @item "Fatal condition while unwinding" A fatal condition was signaled while Chf was unwinding. This is not allowed because is would require another unwind to be recovered. @item "Condition stack overflow" An attempt was made to generate a condition while the Chf condition CHF_F_COND_STACK_FULL (condition stack full) was being signaled. @item "Can't prime a new Chf context" Chf was unable to clone the master Chf context when a thread first attempted to access its context. This message is generated only when multithreading support is enabled. @item "Pthread interaction failed" An unrecoverable error occurred when Chf invoked a @code{pthread} function. This message is generated only when multithreading support is enabled. @end table No message is printed if the @code{abort_code} is @code{CHF_ABORT_SILENT}; this code is used, for example, by the default condition handler to terminate the application when a @code{CHF_FATAL} condition occurs. Notes: @itemize @bullet @item This function is called by other Chf library functions only when they detect an unrecoverable failure. Even if it has a public prototype, the user should never invoke this function. @item @strong{Win32:} Since the standard error stream is not available, this function is able to display the abort message only if it is able to obtain a valid main window handle, that is, if the @code{GetActiveWindow()} function yields a valid value when invoked. @end itemize @end deftypefn @node Library header, , ChfAbort(), Initialization and exit @section Library header @cindex Library header The library header @code{Chf.h} must be included by all source modules using the Chf library. Prior to include it, the following macro definitions must be made: @table @code @item CHF_MODULE_ID This macro must expand into an integer representing the module identifier of the module the source file belongs. The module identifiers with value less than 10 are reserved for Chf internal use. @xref{Reserved module identifiers}. All conditions generated by the source module will use this module identifier. Even if this macro could in principle be redefined through the source, it is generally inconvenient to have functions belonging to different application's modules in the same source file, so it is discouraged. This definition is mandatory. @item CHF_EXTENDED_INFO If this macro is set, all conditions generated by the source module will include the file name and the line number as additional information items. This can be useful for debugging purposes. This definition is optional. @end table @strong{Win32:} The @code{tchar.h} system header must be included before including @code{Chf.h}. @node Condition generation and signal, General condition handling, Initialization and exit, Top @chapter Condition generation and signal @cindex Condition generation and signal @menu * Generating a condition:: * Signaling a condition:: @end menu @node Generating a condition, Signaling a condition, Condition generation and signal, Condition generation and signal @section Generating a condition @cindex Generating a condition When an unusual or noteworthy condition occurs, the application may generate a condition that describes it. @menu * ChfCondition:: * ChfEnd:: * ChfSeverity:: * ChfErrnoCondition:: @end menu @node ChfCondition, ChfEnd, Generating a condition, Generating a condition @subsection ChfCondition @deftypefn Macro {} ChfCondition {...} This macro starts the definition of a condition using the current application's module specifier @code{CHF_MODULE_ID}; it must be followed by these additional, mandatory, arguments: @table @code @item int condition_code This argument is the condition code; it uniquely identifies a condition within the scope of the current application's module. @item ChfSeverity severity This value represents the severity of the condition. @xref{ChfSeverity}. @end table Moreover, zero or more additional argument can follow; they will be immediately combined with the message template corresponding to the pair (@code{CHF_MODULE_ID}, @code{condition_code}) using @code{sprintf()}. All format specifiers of the latter function are allowed in the message template. As stated before, the message template is retrieved using the message retrieval subsystem (@pxref{Message retrieval}) using the current Chf module identifier @code{CHF_MODULE_ID} as the message set, and the condition code @code{condition_code} as the message number. If in the condition stack there isn't any condition yet, a new condition group is created, otherwise the new condition is linked on top of the current condition group. The condition stack supports multiple nested condition groups for use in condition handlers: any condition generated inside a condition handler starts a new condition group that can be individually handled and signaled. This function calls the Chf function @code{ChfAbort()} if one of the following unrecoverable error condition occurs: @itemize @bullet @item Chf has not been initialized correctly (abort code @code{CHF_ABORT_INIT}) @item there is an overflow in the internal buffer used during the generation of the partial message associated with the condition (abort code @code{CHF_ABORT_MSG_OVF}) @item there was an attempt to generate a condition while the Chf condition @code{CHF_F_COND_STACK_FULL} (condition stack full) was being signaled (abort code @code{CHF_ABORT_COND_STACK_OVF}) @end itemize @end deftypefn @node ChfEnd, ChfSeverity, ChfCondition, Generating a condition @subsection ChfEnd @deftypefn Macro {} ChfEnd This macro terminates the generation of the condition, started with @code{ChfCondition}; it must be followed by @code{;}. For example: @example ChfCondition , , ChfEnd; @end example @end deftypefn @c 2.1, cibrario, 26-May-2000 @c Expanded description of severity codes @node ChfSeverity, ChfErrnoCondition, ChfEnd, Generating a condition @subsection ChfSeverity @deftp {Data type} ChfSeverity The severity code of a condition is an enumerated type, and can assume one of the following values: @table @code @item CHF_SUCCESS This condition represents the successful completion of an application's action; when generated in an application's module it is usually signaled immediately after generation, it is not reported to the module caller and does not disrupt the normal control flow of the application. @item CHF_INFO This condition conveys an information message to the application's user, but it in no way represents an error indication; when generated in an application's module it is usually signaled immediately after generation, it is not reported to the module caller and does not disrupt the normal control flow of the application. @item CHF_WARNING This condition has been generated to warn the application's user that a potentially abnormal situation occurred, but the application's module was able to complete successfully the action that was requested to it, perhaps incompletely. It is usually not signaled immediately after generation, it is reported to the caller using some status reporting mechanism, and it requires only a minimal, local disruption of the control flow of the application to be recovered. @item CHF_ERROR An error occurred and the application's module was not able to complete its work, but it still may be possible to perform a local recovery and resume the normal application's control flow. It is usually not signaled immediately after generation and it is reported to the caller using some status reporting mechanism. @item CHF_FATAL A fatal error occurred, and a global recovery action is required, because the normal application's control flow can't be safely resumed. The Chf library enforces that, when @code{ChfSignal()} is called with a fatal condition, the control will never return to the instruction following the @code{ChfSignal()} call. It is usually signaled immediately after generation. @end table @end deftp @node ChfErrnoCondition, , ChfSeverity, Generating a condition @subsection ChfErrnoCondition @deftypefn Macro {} ChfErrnoCondition This macro generates a condition from the current value of the @code{errno} variable. The module identifier of the condition is set to the special value @code{CHF_ERRNO_SET}. The severity is always @code{CHF_ERROR}. @strong{Win32:} This macro is not supported and has no effect when invoked. @end deftypefn @node Signaling a condition, , Generating a condition, Condition generation and signal @section Signaling a condition @cindex Signaling a condition A condition already generated with one of the macros discussed in the previous section can be signaled using the following function, that starts the condition signaling sequence. @menu * ChfSignal():: @end menu @node ChfSignal(), , Signaling a condition, Signaling a condition @subsection ChfSignal() @cindex ChfSignal() @deftypefn Function void ChfSignal (void) @end deftypefn This function signals the current condition group. If the final action requested by the condition handlers invoked during the signaling operation was @code{CHF_CONTINUE} and the overall severity of the condition group was lower than @code{CHF_FATAL}, this function will return to the caller, otherwise either a non-local control transfer will occur (@code{CHF_UNWIND}) or the invoking application/thread will be terminated. During the signaling of a condition group the following actions are accomplished: @itemize @bullet @item First of all, a check is made to ensure that the Chf subsystem has been correctly initialized. If not, the function @code{ChfAbort} is called. @item The state of Chf is changed to @code{CHF_SIGNALING} if it was @code{CHF_IDLE}, and to @code{CHF_SIGNAL_UNWINDING} if it was @code{CHF_UNWINDING}. @item If there is not any active condition group, the function does nothing more, restores the saved Chf state and returns to the caller. @item If there is an active condition group, the currently active condition handlers are invoked, starting from the one registered last. @item Each condition handler can recursively invoke @code{ChfGenerate()} and @code{ChfSignal()}. @code{ChfGenerate()}, when invoked, will create a new condition group, and @code{ChfSignal()} will signal the condition group just created. @item When the Chf state is @code{CHF_SIGNALING}, any new condition group generated but not yet signaled when the current handler exits is merged with the condition group currently being signaled, in order to allow the condition handlers to add their own conditions to the condition group. If the severity of the previous condition group was @code{CHF_FATAL}, the severity of the new group is forced to @code{CHF_FATAL}, too. When the Chf state is @code{CHF_UNWINDING}, the condition group for which the unwind has been requested is 'frozen', no further modifications are allowed on it, and the new condition group is simply discarded. @item The condition handlers calling sequence terminates when either the handler stack is exhausted (all condition handlers have been called) or when an handler requests either the action @code{CHF_CONTINUE}, @code{CHF_UNWIND} or @code{CHF_UNWIND_KEEP}. Please note that the @code{CHF_CONTINUE} action cannot be requested if the severity of the condition group is @code{CHF_FATAL}; when this occurs, the action is automatically changed to @code{CHF_RESIGNAL} instead. @item If the action @code{CHF_CONTINUE} has been requested and it is allowed, Chf discards the current condition group, restored the saved Chf state and returns to the instruction following the call to @code{ChfSignal()}, that started the signaling activities. @item If either one of the actions @code{CHF_UNWIND} or @code{CHF_UNWIND_KEEP} has been requested and it is allowed, that is, no other unwinds are already in progress, the current Chf state is set to @code{CHF_UNWINDING} and all handlers that were registered after the handler that requested the unwind are called again, starting from the one registered last, so that they can perform any final cleanup operation they require for proper operation. The handler that requested the unwind is called again, too, in the same fashion. Immediately after this, the unwinded condition handlers are removed from the handler stack and discarded, the current condition group and any other group generated after it are destroyed, the Chf state is changed back to @code{CHF_IDLE} and a non-local control transfer is executed through a @code{siglongjmp()}, using the @code{unwind_context} associated with the handler that requested the unwind as target. The @code{ChfSignal()} invocation that started the signaling activities will never return to the caller. If the requested action is @code{CHF_UNWIND_KEEP} everything goes as described above, except that the current condition group and any other group generated after it are @strong{not} destroyed, so they can still be accessed after the non-local control transfer has taken place. @item If no handlers were able to handle the condition, the invoking application/thread is terminated with @code{ChfAbort()}. @item If an handler returned an invalid action code and it is not the condition handler that was registered first, a new condition group is generated and immediately signaled, containing the condition @code{CHF_F_INVALID_ACTION} with module identifier @code{CHF_SET}. @end itemize @c 2.1, cibrario, 18-May-2000 @c Renamed 'condition handling' -> 'general condition handling' @node General condition handling, Structured condition handling, Condition generation and signal, Top @chapter Condition handling @cindex Condition handling @menu * Condition handlers:: * Condition descriptors:: * Condition handling state:: * Handler actions:: * Default handler:: @end menu @node Condition handlers, Condition descriptors, General condition handling, General condition handling @section Condition handlers @cindex Condition handlers The Chf library maintains a LIFO stack of active condition handlers. Each condition handler is a function which has type @code{ChfHandler}. Moreover, the functions described below are available to push and pop a condition handler to/from the condition handler stack. @menu * ChfHandler:: * ChfPushHandler():: * ChfPopHandler():: @end menu @node ChfHandler, ChfPushHandler(), Condition handlers, Condition handlers @subsection ChfHandler @cindex ChfHandler @deftp {Data Type} ChfHandler The condition handler data type is defined as follows: @example typedef /* Condition handler */ ChfAction (*ChfHandler)( const ChfDescriptor *, const ChfState, ChfPointer ); @end example The condition handler receives the following arguments when invoked: @table @code @item const ChfDescriptor * is a pointer to the condition group that is being signaled. @item const ChfState represents the current state of the condition handling facility. @item ChfPointer is a copy of the @code{handler_context} pointer passed to the @code{ChfPushHandler()} invocation that established the condition handler. @end table The handler must return an action code, represented by a value of type @code{ChfAction}. Before returning, the condition handler can generate other conditions, without signaling them, with the purpose of better specify the current condition group; these conditions will be added on top of the current group when the handler returns. The next handler, if any, will be invoked on the updated condition group. The severity @code{CHF_FATAL} is 'sticky', that is, any new condition linked to a condition group where the topmost condition has that severity will be forced to the same severity level. If the condition handler itself generates and signals a new condition group, its superior condition handlers will be invoked on the new condition group only. When the new signaling sequence is completed, the old sequence will be resumed if appropriate, i.e. if a superior handler has requested the @code{CHF_CONTINUE} action and the severity of the new condition group allows it to do so. @end deftp @node ChfPushHandler(), ChfPopHandler(), ChfHandler, Condition handlers @subsection ChfPushHandler() @cindex Condition handlers @cindex Adding condition handlers @deftypefn Function void ChfPushHandler (ChfHandler new_handler, void *unwind_context, ChfPointer handler_context) This function pushes the new condition handler @code{new_handler} with its associated @code{siglongjmp()} context, pointed by @code{unwind_context}, into the handler stack. If @code{new_handler} is @code{CHF_NULL_HANDLER}, the special builtin structured condition handling helper is pushed; see @ref{Structured condition handling}, for further information. Moreover, this function saves a copy of the opaque pointer @code{handler_context}; it will be passed to @code{new_handler} upon each subsequent activation, and therefore can be used as a private handler context pointer. The user must ensure that the information pointed by @code{handler_context}, if any, will remain valid until @code{new_handler} is popped from the condition stack. The pointer @code{handler_context} may be set to the special (null) value @code{CHF_NULL_POINTER} to indicate that the handler hasn't any private context information. If, in the future, the handler will request the @code{CHF_UNWIND} action, the @code{sigsetjmp()} function invocation that established @code{unwind_context} will appear to return again. The pointer @code{unwind_context} can be the reserved (null) pointer @code{CHF_NULL_CONTEXT}; in this case, if the handler will request the @code{CHF_UNWIND} action, the invoking application/thread will be silently terminated calling @code{ChfAbort()} with abort code @code{CHF_ABORT_SILENT}. If an error occurs during the execution, the function generates and immediately signals one of the conditions listed below; the function will never return directly to the caller, since all conditions have severity @code{CHF_FATAL}. @table @code @item CHF_F_BAD_STATE Bad Chf state for requested operation. A new handler can be added to the handler stack only if the condition handling subsystem is idle. @item CHF_F_HDLR_STACK_FULL, The handler stack is full and the new handler can't be added. @end table Notes: @itemize @bullet @item This function will call @code{ChfAbort()} with abort code @code{CHF_ABORT_INIT} if Chf hasn't been initialized. @end itemize @end deftypefn @node ChfPopHandler(), , ChfPushHandler(), Condition handlers @subsection ChfPopHandler() @cindex Condition handlers @cindex Removing condition handlers @deftypefn Function void ChfPopHandler (void) This function pops the topmost condition handler from the handler stack and returns to the caller. If an error occurs during the execution, the function generates and immediately signals one of the conditions listed below; the function will never return directly to the caller, since all conditions have severity @code{CHF_FATAL}. @table @code @item CHF_F_BAD_STATE Bad Chf state for requested operation. Handlers can be removed from the handler stack only if the condition handling subsystem is idle. @item CHF_F_HDLR_STACK_EMPTY The handler stack is empty. @end table Notes: @itemize @bullet @item This function will call @code{ChfAbort()} with abort code @code{CHF_ABORT_INIT} if Chf hasn't been initialized. @end itemize @end deftypefn @node Condition descriptors, Condition handling state, Condition handlers, General condition handling @section Condition descriptors @cindex Condition descriptors @deftp {Data Type} ChfDescriptor The condition descriptor contains all information Chf has about a condition code. Its fields must not be accessed directly, but using the macros the Chf library provides for this purpose. @end deftp The following macros are provided to access a condition descriptor: @deftypefn Macro {ChfDescriptor *} ChfGetNextDescriptor (Chf Descriptor *d) @cindex Next condition descriptor Returns to the caller the condition descriptor that hierarchically follows @code{d} in the current condition group, or the special value @code{CHF_NULL_DESCRIPTOR} if @code{d} is the last descriptor of the group. @end deftypefn @deftypefn Macro int ChfGetModuleId (Chf Descriptor *d) @cindex Module identifier Returns to the caller the identifier of the module that generated the condition @code{d}. @end deftypefn @deftypefn Macro int ChfGetConditionCode (Chf Descriptor *d) @cindex Condition Code Returns to the caller the condition code of the condition @code{d}. @end deftypefn @deftypefn Macro ChfSeverity ChfGetSeverity (Chf Descriptor *d) @cindex Severity Returns to the caller the severity level of the condition @code{d}. @xref{ChfSeverity}. @end deftypefn @deftypefn Macro int ChfGetLineNumber (Chf Descriptor *d) @cindex Line number Returns to the caller the source line number where the condition @code{d} was generated. This piece of information is available only if the Chf compile-time option @code{CHF_EXTENDED_INFO} was set when the source file that generated the condition was compiled, otherwise the special value @code{CHF_UNKNOWN_LINE_NUMBER} is returned instead. @end deftypefn @deftypefn Macro {const char *} ChfGetFileName (Chf Descriptor *d) @cindex File name Returns to the caller the file name where the condition @code{d} was generated. This piece of information is available only if the Chf compile-time option @code{CHF_EXTENDED_INFO} was set when the source file that generated the condition was compiled, otherwise the special value @code{CHF_UNKNOWN_FILE_NAME} is returned instead. @end deftypefn @deftypefn Macro {char *} ChfGetPartialMessage (Chf Descriptor *d) @cindex Partial condition message Returns to the caller the partial condition message that was associated with the condition @code{d} when it was generated. The partial condition message contains the result of the execution of @code{sprintf()} using the message template associated with the condition as format, and the ancillary condition arguments as additional arguments. @end deftypefn @node Condition handling state, Handler actions, Condition descriptors, General condition handling @section Condition handling state @cindex Condition handling state @deftp {Data Type} ChfState This enumerated type describes the current state of the Condition Handling Facility. It can have one of the following values: @table @code @item CHF_UNKNOWN The Chf library has not been initialized, or the initialization has failed. Normally, the user never sees this value, because the main use of @code{ChfState} values is inside condition handlers, and they are never invoked when the Chf library has not been initialized correctly. @item CHF_IDLE This is the normal state of the condition handling facility. In this state, the condition stack contains zero or more condition descriptors corresponding to conditions that have been generated but have not been signaled yet. The application follows its normal control flow. @item CHF_SIGNALING The Condition Handling Facility is invoking the hierarchy of active condition handlers because @code{ChfSignal()} has been invoked with a non-empty condition stack. None of the condition handlers invoked so far has requested an unwind operation. @item CHF_UNWINDING The Condition Handling Facility is unwinding one or more condition handlers, because another, superior, handler has requested an unwind operation. All handlers being unwinded are called once with Chf in this state to allow them to perform any final cleanup operation, and immediately after that they are removed from the condition stack. During unwind, the action code returned by the handler being unwinded is ignored. @item CHF_SIGNAL_UNWINDING While Chf was performing an unwind operation, one of the handlers being unwinded has signaled another condition group. The superiors of the signaling handler are invoked with Chf in this state, then the unwind operation is resumed. @end table @end deftp @node Handler actions, Default handler, Condition handling state, General condition handling @section Handler actions @cindex Handler actions @deftp {Data Type} ChfAction Enumerated type representing the set of mutually exclusive actions that a condition handler can request to the condition handling facility. It can have the following values: @table @code @item CHF_CONTINUE Resume the application from the instruction immediately following the @code{ChfSignal()} call that triggered the invocation of the condition handler. This action is not allowed if the severity of the current condition is @code{CHF_FATAL}, since this severity always requires global recovery to take place. In this case the @code{CHF_CONTINUE} is automatically changed to @code{CHF_RESIGNAL} when encountered. @item CHF_RESIGNAL Invoke the next handler in the handler stack with the same condition. This action must be used when the current condition handler was not able to recover the condition. @item CHF_UNWIND Unwind the application's stack and restore the @code{unwind_context} associated with the condition handler, performing a non-local control transfer. @xref{ChfPushHandler()}. @c 2.1, cibrario, 18-May-2000 @c Added descruption of CHF_UNWIND_KEEP @item CHF_UNWIND_KEEP Unwind the application's stack and restore the @code{unwind_context} associated with the condition handler, performing a non-local control transfer. Unlike @code{CHF_UNWIND}, the current condition group at the time of the unwind is @strong{not} destroyed, and can still be accessed after the non-local control transfer has taken place. @end table @end deftp @node Default handler, , Handler actions, General condition handling @section Default handler @cindex Default handler The default condition handler of Chf is automatically pushed into the condition handler stack by the Chf initialization functions. It performs the following functions: @itemize @bullet @item if called during an unwind, it returns immediately to the caller, requesting the action @code{CHF_RESIGNAL}, else @item if the severity of the condition being signaled is greater than @code{CHF_SUCCESS}, it prints the messages associated with the entire condition group on stderr using the standard function @code{ChfBuildMessage()} to build the messages. @strong{Win32: } Since the standard error stream is not available, the default handler does not print anything out. @item if the severity of the condition being signaled is less than @code{CHF_FATAL}, it returns to the caller requesting the action @code{CHF_CONTINUE}, else @item if the @code{CHF_FATAL} condition was @strong{not} signaled during an unwind operation, it returns to the caller requesting the action @code{CHF_UNWIND}, otherwise it requests the action @code{CHF_RESIGNAL}. @end itemize @c 2.1, cibrario, 18-May-2000 @c New chapter: Structured condition handling @node Structured condition handling, Chf conditions, General condition handling, Top @chapter Structured condition handling @cindex Structured condition handling Structured condition handling places the condition handler associated with a block of code next to the block itself, instead of into a separate procedure. Even if it is less flexible and powerful with respect to the general handling method described before, it is often clearer and simpler to implement. Chf supports both styles of condition handling; the structured condition handling is layered above the general one. @menu * Syntax of structured condition handlers:: * Chf behavior during structured condition handling:: @end menu @node Syntax of structured condition handlers, Chf behavior during structured condition handling, Structured condition handling, Structured condition handling @section Syntax of structured condition handlers @cindex Syntax of structured condition handlers The syntax establishing a structured condition handler is as follows: @example ChfTry @{ ... body ... @} ChfCatch @{ const ChfDescriptor *exc = ChfGetTopCondition(); ... condition handler ... @} ChfEndTry; @end example The macros @code{ChfTry}, @code{ChfCatch} and @code{ChfEndTry} expand as follows: @example << @{ sigjmp_buf _chf_sigjmp_buf; if(sigsetjmp(_chf_sigjmp_buf, 1) == 0) @{ ChfPushHandler(CHF_NULL_HANDLER, _chf_sigjmp_buf, CHF_NULL_POINTER); >> @{ ... body ... @} << ChfPopHandler(); @} else @{ >> @{ const ChfDescriptor *exc = ChfGetTopCondition(); ... condition handler ... @} << ChfDiscard(); @} @} >> @end example Above, @code{<<} and @code{>>} mark the starting and ending point of each macro expansion, respectively. The @code{body} is either a statement or a block of statements (a block is shown in the example) to be protected. If an exception with severity equal to @code{CHF_FATAL} is signaled during the execution of @code{body}, control is transferred to the @code{condition handler} following @code{ChfCatch}. The handler can then retrieve the condition group associated with the exception using @code{ChfGetTopCondition()}, as shown in the example, and must perform one of the following actions: @itemize @bullet @item Handle the exception; when the condition handler completes, that is, its last statement has been executed, the current condition group is automatically discarded and control is transferred to the code that follows @code{ChfEndTry}. @item Resignal the exception, possibly after adding one or more conditions to it; in this case, the handler explicitly calls @code{ChfSignal()}. In response, Chf continues to search for a handler that actually handles the exception, in the @code{ChfTry}/@code{ChfCatch} blocks enclosing the current one, in inner to outer order. The control will never be returned to the resignaling handler. @end itemize Notice that it is not possible for the condition handler to resume the thread of execution disrupted by the exception. Resuming is possible only when the signaled condition has severity less than @code{CHF_FATAL}: in this case the @code{condition handler} is not invoked, the usual condition signaling sequence takes place and the @code{CHF_CONTINUE} action requested by any general condition handler is honored. Thus, structured condition handling is further simplified because: @itemize @bullet @item Conditions with severity less than @code{CHF_WARNING} are usually automatically signaled immediately after generation and are not reported to the caller; they are informational conditions only, and they must not disrupt the normal control flow of the application. Accordingly, the structured condition handler is @strong{not} invoked when a success/informational condition is signaled in its @code{ChfTry} body. @item @code{CHF_WARNING} conditions generated by a module are usually not signaled immediately after generation, but are reported to the caller using some status reporting mechanism. When a warning condition is generated by a module, it indicates that its execution has been at least partially successful; this usually means that the disruption of the control flow of the application can be kept to a minimum and handled locally. Accordingly, the structured condition handler is @strong{not} invoked when a warning condition is signaled in its @code{ChfTry} body. @item @code{CHF_ERROR} conditions generated by a module indicate that the module execution has been unsuccessful; they are usually reported to the caller using some status reporting mechanisms. An error condition indicates that a significant disruption of the control flow of the application is required to recover, and that local handling is still possible but could not suffice. Accordingly, the structured condition handler is @strong{not} invoked when an error condition is signaled in its @code{ChfTry} body. Notice also that if the @code{ChfTry} body is not able to locally recover the condition, it can add a @code{CHF_FATAL} condition to the condition group and signal the modified group, thus triggering the invocation of the structured condition handler. @item @code{CHF_FATAL} conditions are usually signaled immediately after generation and always require a global recovery action. Accordingly, the structured condition handler is invoked when a warning condition is signaled in its @code{ChfTry} body. @end itemize Notice also that control is transferred to the structured exception handler by means of a @code{siglongjmp()} sequence. Therefore, if the structured exception handler needs to access automatic variables, they should be declared @code{volatile}. If no handlers are able to handle an exception, the default Chf condition handler is invoked last. @xref{Default handler}, for a more detailed description of its operation. If no exceptions are raised during the execution of @code{body}, the @code{condition handler} is skipped and execution continues immediately after @code{ChfEndTry}. @node Chf behavior during structured condition handling, , Syntax of structured condition handlers, Structured condition handling @section Chf behavior during structured condition handling @cindex Chf behavior during structured condition handling When a condition is signaled and the special structured condition handling helper is invoked, the following sequence of events occurs: @itemize @bullet @item Chf transitions to state @code{CHF_SIGNALING} and starts the handler calling sequence. @item If any handler invoked before the structured condition handling helper requests either the @code{CHF_CONTINUE} or the @code{CHF_UNWIND} action, that action is executed as usual. @item When invoked, the structured condition handling helper immediately requests the action @code{CHF_UNWIND_KEEP}. @item Chf transitions to state @code{CHF_UNWINDING} and invokes all handlers registered after the structured condition handling helper again. Such handlers can then perform whatever final cleanup operations they need. @item Chf invokes the structured condition handling helper again; the helper immediately returns without doing anything, since Chf is now in state @code{CHF_UNWINDING}. @item Chf transitions to the @code{CHF_IDLE} state and performs a non-local control transfer to the structured condition handler's unwind context; this corresponds to the code that follows @code{ChfCatch}. The current condition group is not removed from the condition stack. @item Since the current condition group has not been removed from the condition stack, the code that follows @code{ChfCatch} can freely access the condition group using @code{ChfGetTopCondition()} and @code{ChfGetNextDescriptor()}. @item If any new condition is generated in this phase, it is merged with the current condition group; the condition group can be re-signaled at will by invoking @code{ChfSignal()}. @item Immediately after the code that follows @code{ChfCatch} completes, @code{ChfDiscard()} is automatically invoked to remove the topmost condition group from the stack. @end itemize If the structured condition handling helper is invoked when Chf is in @code{CHF_SIGNAL_UNWINDING}, it immediately requests the @code{CHF_RESIGNAL} action, because a further unwind request is neither allowed nor useful in this case. The structured condition handling helper makes no use of @code{handler_context}. In summary, the following structured condition handling macros are currently available: @menu * ChfTry:: * ChfCatch:: * ChfEndTry:: @end menu @node ChfTry, ChfCatch, Chf behavior during structured condition handling, Chf behavior during structured condition handling @subsection ChfTry @deftypefn Macro {} ChfTry {...} This macro introduces a new structured condition handling body. The body is either a statement or a block of statements to be protected: if a @code{CHF_FATAL} exception is signaled during its execution, control is transferred to the condition handling code following @code{ChfCatch}. @end deftypefn @node ChfCatch, ChfEndTry, ChfTry, Chf behavior during structured condition handling @subsection ChfCatch @deftypefn Macro {} ChfCatch {...} This macro must follow @code{ChfTry} and introduces a new structured condition handler following it; the handler can be either a statement or a block of statements. If a @code{CHF_FATAL} exception is signaled during the execution of the body protected by @code{ChfTry}, control is transferred to the condition handling code following @code{ChfCatch}. @end deftypefn @node ChfEndTry, , ChfCatch, Chf behavior during structured condition handling @subsection ChfEndTry @deftypefn Macro {} ChfEndTry This macro marks the end of a body/condition handler pair. @end deftypefn @node Chf conditions, Message retrieval, Structured condition handling, Top @chapter Chf conditions @cindex Chf conditions The Chf library can itself generate and signal the following conditions. All conditions are fatal, i.e. require a global recovery action to take place to be handled. @deftypefn Macro {} CHF_F_COND_STACK_FULL The user attempted to generate a condition while the condition stack was full; this condition is generated anyway using a reserved stack entry. No additional conditions can be generated until the handling of this condition is completed, otherwise the application will be aborted. @end deftypefn @deftypefn Macro {} CHF_F_HDLR_STACK_FULL The function @code{ChfPushHandler()} was called while the handler stack was full; the new handler is not registered and this condition is signaled using the old handler hierarchy. @end deftypefn @deftypefn Macro {} CHF_F_HDLR_STACK_EMPTY A function requiring at least one condition handler to be active found an empty handler stack. @end deftypefn @deftypefn Macro {} CHF_F_BAD_STATE The current state of Chf was not appropriate to invoke a certain Chf function. The invoked function does not do anything but signaling this condition. @end deftypefn @deftypefn Macro {} CHF_F_INVALID_ACTION During the current signaling sequence an handler returned an invalid action code. A new condition group, containing only this condition, is generated and immediately signaled. The first handler called to handle the new condition group will be the handler registered immediately before the faulting one. @end deftypefn @deftypefn Macro {} CHF_F_MALLOC Many Chf functions dynamically allocate memory. This condition is generated and signaled when a dynamic memory allocation attempt failed, and the library was unable to recover in another way. @end deftypefn @deftypefn Macro {} CHF_F_NOT_AVAILABLE The function is not available on the current platform. This condition is returned by some Chf initialization functions instead of being signaled, because it prevents the Chf subsystem to be initialized and, therefore, to function properly. @end deftypefn @deftypefn Macro {} CHF_F_SETLOCALE The @code{setlocale()} function failed during the initialization of the message catalog-based message retrieval subsystem. This condition is returned by the Chf initialization function instead of being signaled, because it prevents the Chf subsystem to be initialized and, therefore, to function properly. @end deftypefn @deftypefn Macro {} CHF_F_CATOPEN The @code{catopen()} function failed during the initialization of the message catalog-based message retrieval subsystem. This condition is returned by the Chf initialization function instead of being signaled, because it prevents the Chf subsystem to be initialized and, therefore, to function properly. @end deftypefn @node Message retrieval, Multithreading support, Chf conditions, Top @chapter Message retrieval @cindex Message retrieval The message retrieval subsystem is responsible to retrieve the message fragments needed by the Chf library to generate the messages associated with condition codes. Basically, given a message set identifier (that usually has the same value as the module identifier for which the condition is being generated) and a message number (that usually has the same value as the condition code), it must retrieve and return to the caller a suitable message associated to it. It the message cannot be found, it must return a default message pointer Chf provides. Some module identifiers/message sets are used for special purposes. @xref{Reserved module identifiers}. @menu * Retrieving a message:: * Reserved module identifiers:: * Defining a new message retrieval subsystem:: @end menu @node Retrieving a message, Reserved module identifiers, Message retrieval, Message retrieval @section Retrieving a message The following functions directly interact with the message retrieval subsystem: @menu * ChfGetMessage():: * ChfBuildMessage():: @end menu @node ChfGetMessage(), ChfBuildMessage(), Retrieving a message, Retrieving a message @subsection ChfGetMessage() @deftypefn Function {const char *} ChfGetMessage (const int module_id, const int condition_code, const char *default_message) This function transparently uses the Chf message retrieval subsystem to retrieve the message associated with the pair (@code{module_id}, @code{condition_code}) and returns a pointer to it. The function will return @code{default_message} instead, if it was not able to retrieve the message. If @code{module_id==CHF_ERRNO_SET}, the function will additionally invoke @code{strerror()}, if necessary, to retrieve the message. @strong{Win32:} Since @code{strerror()} is not supported, the additional last-chance translation described above cannot be performed. Notes: @itemize @bullet @item The returned pointer points to per-thread static storage, which can be overwritten by subsequent calls to this function. @end itemize @end deftypefn @node ChfBuildMessage(), , ChfGetMessage(), Retrieving a message @subsection ChfBuildMessage() @deftypefn Function {char *} ChfBuildMessage (const ChfDescriptor *descriptor) This function builds the message associated with the given condition descriptor and returns a pointer to a string containing it. The message has a standard format and provides the following information items: @itemize @bullet @item The application's name given to the Chf library during initialization, if the condition is the topmost within a condition group; otherwise, the message starts with an horizontal tab character. @item The name of the module that generated the condition. @item If available, the file name and line number of the source where the condition was generated. @item The severity code of the message. @item The message associated with the condition code, including any ancillary information provided during condition generation. @end itemize Notes: @itemize @bullet @item This function will call @code{ChfAbort()} with abort code @code{CHF_ABORT_INIT} if Chf hasn't been correctly initialized. @item The returned pointer points to per-thread static storage, which can be overwritten by subsequent calls to this function. @item @strong{Win32:} to save space, the application's name and severity code are not included in the message. @end itemize @end deftypefn @node Reserved module identifiers, Defining a new message retrieval subsystem, Retrieving a message, Message retrieval @section Reserved module identifiers @cindex Reserved module identifiers The following module identifiers are currently used by the Chf library; all module identifiers with value less than 10 are reserved for future use. @table @code @item 1 This module identifier is used as a message set identifier to retrieve the names of the other application's modules. In particular, to retrieve the name of the application's module @code{m}, the message @code{m} of message set @code{1} is retrieved. @item 2 This module identifier is used to identify the conditions generated by the Chf library itself. @item 3 This module identifier is used as a message set identifier to retrieve the messages associated with the @code{errno} error codes. If the retrieve is unsuccessful, @code{strerror()} is used instead. @end table @strong{Win32:} In addition, the current implementation of the message retrieval subsystem on Win32 imposes the following limits: @code{0 <= condition_code <= 999}, @code{0 <= module_id <= 64}. @c 2.1, cibrario, 18-May-2000 @c Completed section on defining a new mrs @node Defining a new message retrieval subsystem, , Reserved module identifiers, Message retrieval @section Defining a new message retrieval subsystem @cindex Defining a new message retrieval subsystem The Chf library has a generic interface towards the message retrieval subsystem (MRS); therefore, any subsystem can be used, provided it follows the guidelines described below: @itemize @bullet @item A copy of the @code{mrs_data} argument of @code{ChfInit()} is passed to each MRS function when it is invoked. It can be used to hold a pointer to a private MRS data structures. @item The @code{mrs_get} function has the following arguments: @itemize @bullet @item A copy of the @code{mrs_data} argument of @code{ChfInit()}. @item An @code{int}, representing the module identifier of the condition message template/fragment to be retrieved. @item An @code{int}, representing the condition code of the condition message template/fragment to be retrieved. @item A @code{char *}, pointing to a default message template/fragment to be returned if the message retrieval fails. @end itemize The function must attempt to retrieve the message template/fragment associated with the pair (module identifier, condition code) and return it to the caller; if the retrieval fails, the default message must be returned instead. @item The @code{mrs_exit} function is invoked when Chf is about to exit. It has as argument a copy of the @code{mrs_data} argument or @code{ChfInit()} and must perform any cleanup operation the MRS needs. It is guaranteed that no other MRS function will be called after a successful invocation of @code{mrs_exit}. @item When multithreading support is enabled, the MRS must support multiple, concurrent invocations made by different application's threads. The same value of @code{mrs_data} is common to all threads and cannot be changed after initialization. @end itemize @c 2.1, cibrario, 18-May-2000 @c New chapter on multithreading support; revised all other chapters to @c take multithreading support into account, too. @node Multithreading support, Other useful macro definitions, Message retrieval, Top @chapter Multithreading support @cindex Multithreading support When compiled appropriately, the Chf library supports multithreading, and maintains one Chf context per active thread. Multithreading support is enabled when the cpp macro @code{_REENTRANT} is defined. @strong{Win32:} Multitreading support is not provided yet. When multithreading support is enabled, the following modifications to the default Chf behavior come into effect: @itemize @bullet @item @code{ChfInit()} no longer initializes the condition stack, the condition handler stack and the message buffer immediately; instead, one copy of these context elements will be allocated for each active thread in the application, when it first invokes any other Chf function. Also, per-thread Chf contexts are dynamically destroyed when the owning thread terminates. @item Condition generation and both general and structured condition handling work as before inside each application's thread. All threads share the same values for @code{condition_stack_size}, @code{handler_stack_size} and @code{exit_code}, but are otherwise fully independent with respect to condition handling, because each of them has a private Chf context. @item @code{ChfAbort()} no longer exits the whole application when the @code{CHF_ABORT} Chf flag not set; instead, it exits the invoking thread only. @item Almost all Chf functions can trigger the @code{CHF_ABORT_GET_CONTEXT} and @code{CHF_ABORT_PTHREAD} aborts, if they fail to correctly manage dynamic Chf context creation and/or @code{pthread} interactions. @item All Chf functions, except @code{ChfInit()} and @code{ChfExit()} no longer check whether Chf has been correctly initialized or not: that check would have been too time-consuming in a multithreaded environment. As a consequence, invoking a Chf function when Chf has not been correctly initialized has unpredictable effects instead of neatly aborting the application with abort code @code{CHF_ABORT_INIT}. @item The performance of the Chf condition generation and signaling functions is likely to decrease, because Chf must retrieve its per-thread context dynamically instead of referring to a static storage area. @end itemize @node Other useful macro definitions, Other useful functions, Multithreading support, Top @chapter Other useful macro definitions @cindex Other useful macro definitions @deftypefn Macro {} CHF_MAX_MESSAGE_LENGTH Represents the maximum allowable length for condition messages. @end deftypefn @deftypefn Macro {} CHF_LIBRARY_ID It is a string representing the Chf library identifier; the identifier contains also the library release number. @end deftypefn @c 2.1, cibrario, 18-May-2000 @c New macros @deftypefn Macro {} CHF_MAJOR_RELEASE_NUMBER It is an integer representing the Chf library major release number. @end deftypefn @deftypefn Macro {} CHF_MINOR_RELEASE_NUMBER It is an integer representing the Chf library minor release number. @end deftypefn @deftypefn Macro {} CHF_MODULE_NAMES_SET Contains the integer identifier of the message set whose messages are used to retrieve the names of the application's modules. It has the value 1. @end deftypefn @deftypefn Macro {} CHF_SET Contains the integer identifier of the message set containing the condition messages Chf uses internally. It has the value 2. @end deftypefn @deftypefn Macro {} CHF_ERRNO_SET Contains the integer identifier of the message set containing the condition messages for @code{errno} codes. It has the value 3. @end deftypefn @deftypefn Macro {} ChfChar This macro is used to make portable declarations of character variables, and is mapped into either @code{char} or @code{TCHAR} depending on the platform. @end deftypefn @deftypefn Macro {} ChfText (x) This macro is used to make portable declarations of character strings, and is mapped into either @code{x} or @code{_T(x)} depending on the platform. @end deftypefn @deftypefn Macro {} ChfSigjmp_buf This macro is mapped into either @code{sigjmp_buf} or @code{jmp_buf}, depending on whether the platform supports @code{sigjmp_buf} contexts or not. @end deftypefn @deftypefn Macro {} ChfSigsetjmp (x,y) This macro is mapped into either @code{sigsetjmp()} or @code{setjmp()}, depending on whether the platform supports @code{sigjmp_buf} contexts or not. In the latter case argument @code{x} is ignored. @end deftypefn @deftypefn Macro {} ChfSiglongjmp (x,y) This macro is mapped into either @code{siglongjmp()} or @code{longjmp()}, depending on whether the platform supports @code{sigjmp_buf} contexts or not. @end deftypefn @node Other useful functions, Changes since release 1, Other useful macro definitions, Top @chapter Other useful functions @cindex Other useful functions @deftypefn Function void ChfDiscard (void) This function discards the topmost condition group currently in the condition stack, without signaling it. The function does nothing if the condition stack is empty. This function uses the function @code{ChfAbort()} to abort the application if Chf has not been initialized correctly (abort code @code{CHF_ABORT_INIT}). @end deftypefn @deftypefn Function {const ChfDescriptor *} ChfGetTopCondition (void) This function returns to the caller a pointer to the topmost condition of the current condition group. It generates and immediately signals the condition @code{CHF_F_BAD_STATE} if the current condition group is empty. This function can be useful to retrieve the complete description of a condition for functions that, when an error occurs, generate a condition and return to the caller a generic error indication, such as a distinguished return value. The same function can also be useful in a structured exception handler, to retrieve the condition descriptor associated with the exception to be handled. Notes: @itemize @bullet @item During condition signaling, Chf creates a new, empty, condition group immediately before starting the invocation sequence of the condition handlers, as previously described. Therefore @code{ChfGetTopCondition()}, when called from a condition handler, will return a pointer to the top condition generated during the handling ONLY, if any, and NOT to the top condition of the condition group being signaled. The latter pointer is directly available, as an argument, to condition handlers. @item When called from a structured exception handler, @code{ChfGetTopCondition()} works as expected, that is, it returns a pointer to the top condition of the condition group associated with the exception being handled. @item This function will call @code{ChfAbort()} with abort code @code{CHF_ABORT_INIT} if Chf hasn't been correctly initialized. @item The returned pointer is no longer valid when any other Chf function is called after @code{ChfGetTopCondition()}. @end itemize @end deftypefn @c 2.1, cibrario, 18-May-2000 @c New chapter on changes since release 1 @node Changes since release 1, Changes since release 2.1, Other useful functions, Top @chapter Changes since release 1 @cindex Changes since release 1 @itemize @bullet @item Chf now supports structured condition handling. @xref{Structured condition handling}. @item Chf now supports multithreaded applications; each thread has its own Chf context. Multithreading support is conditionally enabled by linking a multithreaded version of the Chf library. @xref{Multithreading support}. @item Chf now supports the conditional save and restore of signal masks in unwind contexts (@code{sigjmp_buf} contexts instead of @code{jmp_buf}). @item The method of passing unwind contexts as arguments is now consistent with that used by @code{sigsetjmp()}; in particular, it is no longer necessary to reference the contexts with @code{&}. @item Some more useful macro definitions have been added to @code{Chf.h}. @xref{Other useful macro definitions}. @end itemize @c 2.2, cibrario, 25-Jan-2001 @c New chapter on changes since release 2.1 @node Changes since release 2.1, Function Index, Changes since release 1, Top @chapter Changes since release 2.1 @cindex Changes since release 2.1 @itemize @bullet @item Chf now offers limited support of Unicode-based Win32 platforms, notably Windows CE. @end itemize @node Function Index, Data Type Index, Changes since release 2.1, Top @unnumbered Function Index @printindex fn @node Data Type Index, Concept Index, Function Index, Top @unnumbered Data Type Index @printindex tp @c @node Variable Index, Concept Index, Data Type Index, Top @c @unnumbered Variable Index @c @printindex vr @node Concept Index, , Data Type Index, Top @unnumbered Concept Index @printindex cp @contents @bye