home *** CD-ROM | disk | FTP | other *** search
- /*
- #### # # # #
- # # # # # The FreeWare C library for
- # # ## ### # # # # ### RISC OS machines
- # # # # # # # # # # # ___________________________________
- # # #### ### ## # # # #
- # # # # # # # # # # Please refer to the accompanying
- #### ### #### # # ##### # ### documentation for conditions of use
- ________________________________________________________________________
-
- File: Error2.h
- Author: Copyright © 1995 Julian Smith
- Version: 1.02 (01 Dec 1995)
- Purpose: General error handling.
- These routines are intended to allow automatic error-safety.
-
- History: 1.00 (17 Jan 1995) JS
- 1.01 (15 Nov 1995) JS Ensured #define for Desk_Error2_CheckOS
- isn't done when making the actual Error2
- library.
- 1.02 (01 Dec 1995) JS Added Desk_Error2_HandleAllSignals.
- */
-
-
-
-
- /*
-
- General info on the Error2 library:
-
- The Error2 library is intended to provide a central error-handling
- system.
-
-
- The system is very simple, but hopefully sufficiently general to allow
- whatever sort of error-handling is required. The core functionality is
- provided by Desk_Error2_Handle(), Desk_Error2_SetHandler(), Desk_Error2_Exit() and the
- structure Desk_error2_block:
-
- Whenver a function discovers an error (eg out of memory), it should set
- up an Desk_error2_block to contain details of the error and call
- Desk_Error2_Handle, passing the address of the Desk_error_block. Many DeskLib
- functions already do this.
-
- Desk_Error2_Handle will call the function registered with Desk_Error2_SetHandler,
- passing it the (Desk_error_block*). It is up to this function to deal with
- the error if it can (in which case it should return Desk_error2_HANDLED).
-
- If it can't deal with the error, it should return a (Desk_error_block*) -
- probably the same one it received.
-
- Desk_Error2_Handle will call Desk_Error2_Exit(), which terminates the program, if
- the error wasn't handled, or return to its caller if the error was
- handled.
-
-
- Note that only one error handler is used - there is no Desk_Event_-type
- system for sending different errors to different handlers, or passing
- unhandled errors on to alternative error handlers. The Desk_Error3_ (not 2)
- functions do this sort of thing (using the Error2 system as a base), but
- they are completely un-tested at the moment.
-
-
- The rest of the Error2 system consists of:
-
- Desk_error2_globalblock is a global Desk_error2_block which is for anyone's use.
-
- Desk_Error2_CheckOS - Simple wrapper which calls Desk_Error2_Handle if a function
- which return an (Desk_os_error*), such as SWI veneers, returns non-NULL.
-
-
- Desk_Error2_Verbose is an error handler which simply outputs diagnostic info
- and then calls abort(). It is intended for use when debugging.
-
- Desk_Error2_SignalHandler is an ANSI C signal handler for use with signal().
- It sets up Desk_error2_globalblock to contain info about the signal, and then
- calls Desk_Error2_Handle
-
- Desk_Error2_HandleText is useful for generating an error which just consists
- of some text. Desk_Error2_HandleTextf is similar, but uses printf-style
- formatting.
-
-
- See the individual declarations in this header file for more info.
-
-
- NB, the function 'Desk_JumpAuto_Error2Handler', in DeskLib's 'Jump'
- sublibrary, is a very useful error-handler. It uses the JumpAuto system
- to do a longjmp back to the most recent setjmp place, allowing pseudo
- C++ try...throw...catch constructs.
-
-
-
-
- Future plans: A system is needed to allow apps to be given their own
- Desk_error2_type values. eg. int Desk_Error2_GetNewErrorType(). Alternatively,
- negative error types could be reserved for application use, and positive
- for DeskLib libraries.
-
- */
-
-
-
-
-
- #ifndef __Desk_Error2_h
- #define __Desk_Error2_h
-
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- #include <stdio.h>
- #include <stdarg.h>
-
- #ifndef __Desk_Error_h
- #include "Error.h"
- #endif
-
- #ifndef __Desk_Jump_h
- #include "JumpRaw.h"
- #endif
-
-
-
- typedef enum {
- Desk_error2_type_NONE = 0,
- Desk_error2_type_MISC = 1, /* Miscellaneous error */
- Desk_error2_type_OSERROR = 2, /* A SWI returned an error. */
- Desk_error2_type_DESKMEM = 3, /* A Desk_DeskMem_ error. */
- Desk_error2_type_SIGNAL = 4, /* A signal was raised. */
- Desk_error2_type_MEM = 5, /* A Desk_Mem_ error (NIY) */
- Desk_error2_type_TEXT = 6 /* An error with a text message */
- }
- Desk_error2_type;
- /*
- Categories of error. Used in Desk_error2_block.
-
- Note that the values of these enums will never change (after the first
- official release of DeskLib > 2.30), so that DeskLib DLLs will still
- work.
- */
-
-
- typedef struct Desk_error2_block {
- Desk_error2_type type;
-
- union {
- void* misc;
- const Desk_os_error* oserror;
- struct Desk_deskmem_errorblock* deskmem;
- int signal;
- /* struct Desk_mem_errorblock* ??? mem; */
- const char* text;
- }
- data;
- }
- Desk_error2_block;
- /*
- Contains information about an error.
-
- 'type' tells you roughly what sort of error has occurred. For many
- purposes, this will be all you need.
-
- Depending on the value of 'type', use
- data.misc/oserror/deskmem/signal/text.
-
- See DeskLib:DeskMem.h for definition of struct Desk_deskmem_errorblock - it
- isn't included here so that you can use Error2 without necessarily
- pulling in DeskMem.
-
- In general, any sublibrary-specific error type will have its own
- structure defined in the sublibrary, so that this header file doesn't
- have to know about all errors.
- */
-
-
-
-
-
-
- void Desk_Error2_Init_JumpSig( void);
- /*
- This sets up the standard Desk error-handling system. It simply calls
- Desk_Error2_SetHandler( Desk_JumpAuto_Error2Handler) and
- Desk_Error2_HandleAllSignals().
- */
-
-
-
-
- void Desk_Error2_Handle( Desk_error2_block* error);
- /*
- This function should be called if an error condition arises which can't
- be coped with locally.
-
- It calls the function registered with Desk_Error2_SetHandler. If this
- function returns, Desk_Error2_globalblock will contain info relating to
- how the problem was solved.. Normally, it will simply do a longjmp.
-
- If there us nowhere to longjmp, it will call Desk_Error2_Exit.
- */
-
-
-
- #define Desk_Error2_Try Desk_JumpAuto_Try
-
- #define Desk_Error2_Catch Desk_JumpAuto_Catch
-
- #define Desk_Error2_EndCatch Desk_JumpAuto_EndCatch
-
- #define Desk_Error2_TryCatch Desk_JumpAuto_TryCatch
-
-
-
- Desk_error2_block *Desk_Error2_Exit( Desk_error2_block *error);
- /*
- Terminates program by calling Desk_Error_ReportFatal with a default error
- message.
-
- Useful to do a 'Desk_Error2_SetHandler( Desk_Error_Exit) to garrantee any error
- will terminate the program with a message.
- */
-
- Desk_error2_block *Desk_Error2_VerboseExit( Desk_error2_block *error);
- /*
- Useful for debugging / command-line programs. Uses Desk_Error_ReportFatal to
- give a description of the error that occurred.
-
- Useful to do a 'Desk_Error2_SetHandler( Desk_Error_VerboseExit) to garrantee any
- error will terminate the program with a message.
-
- Desk_Error2_VerboseExit only knows about the error types in the Desk_error2_type
- enum. Hence if you have your own error type, you should write your own
- verbose exit handler.
- */
-
-
-
-
- typedef int (*Desk_Error2_vprintf_fn)( void* reference, const char* format, va_list va);
- /*
- A function-type similar to vfprintf, except that the first parameter is
- a (void*).
- */
-
- typedef int (*Desk_Error2_printf_fn)( void* reference, const char* format, ...);
- /*
- A function-type similar to fprintf, except that the first parameter is a
- (void*).
- */
-
- void Desk_Error2_VDescribe( Desk_Error2_vprintf_fn fn, void* reference, const Desk_error2_block* error);
- /*
- Sends text about 'error' to 'fn', passing 'reference'.
- */
-
- void Desk_Error2_FDescribe( Desk_Error2_printf_fn fn, void* reference, const Desk_error2_block* error);
- /*
- Sends text about 'error' to 'fn', passing 'reference'.
- */
-
- void Desk_Error2_Describe( FILE* stream, const Desk_error2_block* error);
- /*
- Uses Desk_Error2_VDescribe to send info about 'error' to 'stream'.
- */
-
-
-
- typedef Desk_error2_block* (*Desk_error2_handler)( Desk_error2_block *error);
- /*
- The type of a function which tries to handles errors - the function
- returns Desk_error2_HANDLED if succesfull. Use Desk_Error2_SetHandler to register
- such a handler function with Error2.
- */
-
- #define Desk_error2_HANDLED (NULL)
- /*
- An Desk_error2_handler should return this if it has dealt with an error.
- */
-
-
-
- #define Desk_Error2_SetHandler( handlerfn) Desk_error2__handlerfn = (handlerfn)
- /*
- Sets the handler to be called by Desk_Error2_Handle.
- */
-
- #define Desk_Error2_GetHandler() Desk_error2__handlerfn
- /*
- Returns the current handler.
- */
-
-
-
- int Desk_Error2_GetNewErrorType( void);
- /*
- Returns a unique error number. Useful if an application (or part of an
- application) wants to have its own error type.
- */
-
-
-
- void Desk_Error2_CheckOS( const Desk_os_error *error);
- /*
- A simple error-handler for use with functions which return an
- (Desk_os_error*). If error!=NULL, it sets up Desk_error2_globalblock
- appropriately for 'error', and calls Desk_Error2_Handle(
- Desk_error2_globalblock).
-
- Use like:
-
- Desk_Error2_CheckOS( _swix( ...);
-
- When Desk_DEBUG is defined, Desk_Error2_CheckOS is macro-ed to
- Desk_Error2_CheckOS_Debug, which uses Desk_error_PLACE to output the
- place where the error occurred.
- */
-
-
-
-
- void Desk_Error2_CheckOS_Debug( const Desk_os_error *error, const char *place);
- /*
- Similar to Desk_Error2_CheckOS, except that it expects an extra string
- argument, for use with the Desk_DeskLib_DEBUG-version of Desk_Error2_CheckOS.
- */
-
-
-
- #if defined( Desk_DeskLib_DEBUG) && !defined( Desk__making_Error2)
-
- #define Desk_Error2_CheckOS( oserror) Desk_Error2_CheckOS_Debug( oserror, Desk_error_PLACE)
- /*
- This macro is defined for debugging purposes. It behaves in the same
- way, except that the 'text' field of Desk_error2_globalblock is set to
- Desk_error_PALCE, allowing an error-handler to display where the error came
- from.
- */
- #endif
-
-
-
- void Desk_Error2_CheckBOOL( Desk_bool error);
- /*
- Calls Desk_Error2_Handle if error!=NOERROR.
- */
-
-
-
- void Desk_Error2_HandleText( const char* text);
- /*
- Sets up Desk_error2_globalblock to contain the text message and than calls
- Desk_Error2_Handle
- */
-
-
- void Desk_Error2_HandleTextf( const char* text, ...);
- /*
- Sets up Desk_error2_globalblock to contain the text message and than calls
- Desk_Error2_Handle. The text is specified as with printf.
-
- Note that the text is sprintf-ed into an internal static 252-byte block,
- and no checking is done that it isn't too long.
- */
-
-
-
-
- void Desk_Error2_SignalHandler( int signalnumber);
- /*
- This function sets up Desk_error2_globalblock to contain information about
- the signal number 'signalnumber', and then calls Desk_Error2_Handle.
-
- To use, register Desk_Error2_SignalHandler with the ANSI 'signal()' function
- for all the signals that you want to be treated with the Error2-library
- mechanism, eg:
-
- int main( void)
- {
- signal( SIGFPE, &Desk_Error2_SignalHandler);
- ...
- }
-
- Note that when a signal occurs, ANSI C resets signal handling for the
- signal. To get around this, when called, Desk_Error2_SignalHandler calls
- signal() to re-register itself for the specified signal.
-
- You shouldn't call Desk_Error2_SignalHandler directly.
- */
-
-
-
- void Desk_Error2_HandleAllSignals( void);
- /*
- This registers Desk_Error2_SignalHandler with signal() for all signals
- (SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM, SIGSTAK, SIGUSR1,
- SIGUSR2, SIGOSERROR).
-
- This could be useful when debugging.
- */
-
-
-
- void Desk_Error2_ClearErrorBlock( Desk_error2_block *error);
- /*
- Clears the various fields in 'error'. Useful when setting up an error
- block.
- */
-
- #ifdef Desk__using_SDLS
- extern Desk_error2_block* Desk_Error2__Ref_globalblock( void);
- extern Desk_error2_handler* Desk_Error2__Ref__handlerfn( void);
- #endif
-
-
- #if defined( Desk__using_SDLS) && !defined( Desk__making_Error2)
-
- #define Desk_error2_globalblock (*Desk_Error2__Ref_globalblock())
- #define Desk_error2__handlerfn (*Desk_Error2__Ref__handlerfn())
-
- #else
-
- extern Desk_error2_block Desk_Error2_globalblock;
- /*
- A global Desk_error2_block, for use by anyone. It is used by Desk_Error2_HandleOS
- etc.
- */
-
- extern Desk_error2_handler Desk_error2__handlerfn;
- /*
- This is a global pointer to the function which is called by
- Desk_Error2_Handle. Use the macros Desk_Error2_SetHandler and
- Desk_Error2_GetHandler to access it.
-
- Set to NULL initally.
- */
-
- #endif
-
-
-
- #define Desk_Error2_ReThrow() Desk_Error2_Handle( &Desk_Error2_globalblock)
-
-
-
- extern const char *Desk_Error2_signalnames[];
- /*
- Array of textual descriptions of signals.
- */
-
- void Desk_Error2_ConvertToOS( Desk_os_error* oserror, Desk_error2_block* error2);
- /*
- Makes the os_error pointed to by 'oserror' contain info from 'error2'.
- */
-
-
- #define Desk_Error2_ConvertToOS2() (Desk_Error2_ConvertToOS( &Desk_error_global, &Desk_Error2_globalblock), &Desk_error_global)
- /*
- Treat like:
- Desk_os_error* Desk_Error2_ConvertToOS2( void);
-
- Returns the current Desk_Error2 error converted to a (Desk_os_error*).
- Useful in functions which need to return a (os_error*) - eg:
-
-
- Desk_os_error* Foo( ...)
- {
- Desk_Error2_Try {
- // Call various functions which might raise a Desk_Error2 error
- }
- Desk_Error2_Catch {
- // Clean up.
- return Desk_Error2_ConvertToOS2();
- }
- Desk_Error2_EndCatch
- return NULL;
- }
-
- */
-
-
-
-
-
-
-
-
-
-
-
-
-
- /*
- Error3
- ------
-
- Error3 is an Desk_Event_-type library for registering handlers for different
- sorts of error.
-
- To use Error3, simply call Desk_Error3_UseError3() somwhere. This simply
- registers Desk_Error3__Dispatch as Error2's single error-handling function.
-
- Desk_Error3__Dispatch looks for a previously-registered handler which matches
- the error, and calls it.
-
- Hence any calls to Desk_Error2_Handle and Desk_Error2_XHandle (even those from
- within a previously-compiled library, such as DeskLib) will end up being
- dealt with by Error3's registered handler functions.
-
- You shouldn't normally have to call Desk_Error3__Dispatch directly yourself -
- use Desk_Error2_Handle and Desk_Error2_XHandle.
-
- Note that the Error3 calls are completely untested...
- */
-
-
- #define Desk_Error3_UseError3() Desk_Error2_SetHandler( Desk_Error3__Dispatch);
- /*
- Makes all subsequent error handling by Desk_Error2_Handle and Desk_Error2_XHandle
- use the the Error3 system.
- */
-
-
- typedef Desk_error2_block* (*Desk_error3_handler)( Desk_error2_block *error, void *reference);
- /*
- The type of functions which can be registered with Desk_Error2_Claim* to
- handle errors. These functions should return Desk_error2_HANDLED if succesful.
- */
-
- /*void Desk_Error3_ClaimFunction( Desk_error2_fnptr function, Desk_error3_handler handler, void *reference);
- *//*
- Register a handler to be called when an error is raised by 'function'.
-
- Function-specific handlers are checked before type-specific handlers
- (registered with Desk_Error3_ClaimType) and general handlers (registered with
- Desk_Error3_ClaimMisc).
-
- New handlers are added to front of the list of handlers, so they are
- called in preference to any existing handlers.
- */
-
- void Desk_Error3_ClaimType( Desk_error2_type type, Desk_error3_handler handler, void *reference);
- /*
- Register a handler to be called when an error of a particular type
- 'type' occurs.
-
- Type-specific handlers are checked after function-specific ones
- (registered with Desk_Error3_ClaimFunction), and before general handlers
- (registered with Desk_Error3_ClaimMisc).
-
- New handlers are added to front of the list of handlers, so they are
- called in preference to any existing handlers.
- */
-
- void Desk_Error3_ClaimMisc( Desk_error3_handler handler, void *reference);
- /*
- Register a misc handler to be called when any error occurs.
-
- Misc handlers are only checked after function-specific handlers
- (registered with Desk_Error3_ClaimFunction) and type-specific
- handlers (registered with Desk_Error3_ClaimType).
-
- New handlers are added to front of the list of handlers, so they are
- called in preference to any existing handlers.
- */
-
-
- /*void Desk_Error3_ReleaseFunction( Desk_error2_fnptr function, Desk_error3_handler handler, void *reference);
- *//*
- Removes 'handler' from Error3's list of handlers. 'function' and
- 'reference' must be the same as in the call to Desk_Error3_ClaimFunction
- which registered 'handler'.
- */
-
- void Desk_Error3_ReleaseType( Desk_error2_type type, Desk_error3_handler handler, void *reference);
- /*
- Removes 'handler' from Error3's list of handlers. 'type' and 'reference'
- must be the same as in the call to Desk_Error3_ClaimType which registered
- 'handler'.
- */
-
- void Desk_Error3_ReleaseMisc( Desk_error3_handler handler, void *reference);
- /*
- Removes 'handler' from Error3's list of handlers. 'reference' must be
- the same as in the call to Desk_Error3_ClaimFunction which registered
- 'handler'.
- */
-
- Desk_error2_block* Desk_Error3__Dispatch( Desk_error2_block* error, void* reference);
- /*
- Searches for and calls a suitable error-handler for error.
- */
-
-
- #ifdef __cplusplus
- }
- #endif
-
-
- #endif
-