home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 5 / DATAFILE_PDCD5.iso / utilities / d / desklib / !DeskLib / h_doc / Error2 < prev    next >
Encoding:
Text File  |  1996-12-18  |  16.5 KB  |  602 lines

  1. /*
  2.     ####             #    #     # #
  3.     #   #            #    #       #          The FreeWare C library for
  4.     #   #  ##   ###  #  # #     # ###             RISC OS machines
  5.     #   # #  # #     # #  #     # #  #   ___________________________________
  6.     #   # ####  ###  ##   #     # #  #
  7.     #   # #        # # #  #     # #  #    Please refer to the accompanying
  8.     ####   ### ####  #  # ##### # ###    documentation for conditions of use
  9.     ________________________________________________________________________
  10.  
  11.     File:    Error2.h
  12.     Author:  Copyright © 1995 Julian Smith
  13.     Version: 1.02 (01 Dec 1995)
  14.     Purpose: General error handling.
  15.              These routines are intended to allow automatic error-safety.
  16.              
  17.     History: 1.00 (17 Jan 1995) JS
  18.              1.01 (15 Nov 1995) JS Ensured #define for Desk_Error2_CheckOS
  19.                                    isn't done when making the actual Error2 
  20.                                    library.
  21.              1.02 (01 Dec 1995) JS Added Desk_Error2_HandleAllSignals.
  22. */
  23.  
  24.  
  25.  
  26.  
  27. /*
  28.  
  29. General info on the Error2 library:
  30.  
  31. The Error2 library is intended to provide a central error-handling
  32. system.
  33.  
  34.  
  35. The system is very simple, but hopefully sufficiently general to allow
  36. whatever sort of error-handling is required. The core functionality is
  37. provided by Desk_Error2_Handle(), Desk_Error2_SetHandler(), Desk_Error2_Exit() and the
  38. structure Desk_error2_block:
  39.  
  40. Whenver a function discovers an error (eg out of memory), it should set
  41. up an Desk_error2_block to contain details of the error and call
  42. Desk_Error2_Handle, passing the address of the Desk_error_block. Many DeskLib
  43. functions already do this.
  44.  
  45. Desk_Error2_Handle will call the function registered with Desk_Error2_SetHandler,
  46. passing it the (Desk_error_block*). It is up to this function to deal with
  47. the error if it can (in which case it should return Desk_error2_HANDLED).
  48.  
  49. If it can't deal with the error, it should return a (Desk_error_block*) -
  50. probably the same one it received.
  51.  
  52. Desk_Error2_Handle will call Desk_Error2_Exit(), which terminates the program, if
  53. the error wasn't handled, or return to its caller if the error was
  54. handled.
  55.  
  56.  
  57. Note that only one error handler is used - there is no Desk_Event_-type
  58. system for sending different errors to different handlers, or passing
  59. unhandled errors on to alternative error handlers. The Desk_Error3_ (not 2)
  60. functions do this sort of thing (using the Error2 system as a base), but
  61. they are completely un-tested at the moment.
  62.  
  63.  
  64. The rest of the Error2 system consists of:
  65.  
  66. Desk_error2_globalblock is a global Desk_error2_block which is for anyone's use.
  67.  
  68. Desk_Error2_CheckOS - Simple wrapper which calls Desk_Error2_Handle if a function
  69. which return an (Desk_os_error*), such as SWI veneers, returns non-NULL.
  70.  
  71.  
  72. Desk_Error2_Verbose is an error handler which simply outputs diagnostic info
  73. and then calls abort(). It is intended for use when debugging.
  74.  
  75. Desk_Error2_SignalHandler is an ANSI C signal handler for use with signal().
  76. It sets up Desk_error2_globalblock to contain info about the signal, and then
  77. calls Desk_Error2_Handle
  78.  
  79. Desk_Error2_HandleText is useful for generating an error which just consists
  80. of some text. Desk_Error2_HandleTextf is similar, but uses printf-style
  81. formatting.
  82.  
  83.  
  84. See the individual declarations in this header file for more info.
  85.  
  86.  
  87. NB, the function 'Desk_JumpAuto_Error2Handler', in DeskLib's 'Jump'
  88. sublibrary, is a very useful error-handler. It uses the JumpAuto system
  89. to do a longjmp back to the most recent setjmp place, allowing pseudo
  90. C++ try...throw...catch constructs.
  91.  
  92.  
  93.  
  94.  
  95. Future plans: A system is needed to allow apps to be given their own
  96. Desk_error2_type values. eg. int Desk_Error2_GetNewErrorType(). Alternatively,
  97. negative error types could be reserved for application use, and positive
  98. for DeskLib libraries.
  99.  
  100.  */
  101.  
  102.  
  103.  
  104.  
  105.  
  106. #ifndef __Desk_Error2_h
  107. #define __Desk_Error2_h
  108.  
  109. #ifdef __cplusplus
  110.     extern "C" {
  111. #endif
  112.  
  113. #include <stdio.h>
  114. #include <stdarg.h>
  115.  
  116. #ifndef __Desk_Error_h
  117.     #include "Error.h"
  118. #endif
  119.  
  120. #ifndef __Desk_Jump_h
  121.     #include "JumpRaw.h"
  122. #endif
  123.  
  124.  
  125.  
  126. typedef enum    {
  127.     Desk_error2_type_NONE    = 0,
  128.     Desk_error2_type_MISC    = 1,     /* Miscellaneous error        */
  129.     Desk_error2_type_OSERROR    = 2,     /* A SWI returned an error.     */
  130.     Desk_error2_type_DESKMEM    = 3,     /* A Desk_DeskMem_ error.        */
  131.     Desk_error2_type_SIGNAL    = 4,     /* A signal was raised.        */
  132.     Desk_error2_type_MEM        = 5,     /* A Desk_Mem_ error    (NIY)        */
  133.     Desk_error2_type_TEXT    = 6    /* An error with a text message    */
  134.     }
  135.     Desk_error2_type;
  136. /*
  137. Categories of error. Used in Desk_error2_block.
  138.  
  139. Note that the values of these enums will never change (after the first
  140. official release of DeskLib > 2.30), so that DeskLib DLLs will still
  141. work.
  142.  */
  143.  
  144.     
  145. typedef struct    Desk_error2_block    {
  146.     Desk_error2_type    type;
  147.     
  148.     union    {
  149.         void*                misc;
  150.         const Desk_os_error*            oserror;
  151.         struct Desk_deskmem_errorblock*    deskmem;
  152.         int                signal;
  153.         /* struct Desk_mem_errorblock* ???    mem;    */
  154.         const char*            text;
  155.         }
  156.         data;
  157.     }
  158.     Desk_error2_block;
  159. /*
  160. Contains information about an error. 
  161.  
  162. 'type' tells you roughly what sort of error has occurred. For many
  163. purposes, this will be all you need.
  164.  
  165. Depending on the value of 'type', use
  166. data.misc/oserror/deskmem/signal/text.
  167.  
  168. See DeskLib:DeskMem.h for definition of struct Desk_deskmem_errorblock - it
  169. isn't included here so that you can use Error2 without necessarily
  170. pulling in DeskMem.
  171.  
  172. In general, any sublibrary-specific error type will have its own
  173. structure defined in the sublibrary, so that this header file doesn't
  174. have to know about all errors.
  175.  */
  176.  
  177.  
  178.  
  179.  
  180.  
  181.  
  182. void    Desk_Error2_Init_JumpSig( void);
  183. /*
  184. This sets up the standard Desk error-handling system. It simply calls
  185. Desk_Error2_SetHandler( Desk_JumpAuto_Error2Handler) and
  186. Desk_Error2_HandleAllSignals().
  187.  */
  188.  
  189.  
  190.  
  191.  
  192. void    Desk_Error2_Handle( Desk_error2_block* error);
  193. /*
  194. This function should be called if an error condition arises which can't
  195. be coped with locally.
  196.  
  197. It calls the function registered with Desk_Error2_SetHandler. If this
  198. function returns, Desk_Error2_globalblock will contain info relating to
  199. how the problem was solved.. Normally, it will simply do a longjmp.
  200.  
  201. If there us nowhere to longjmp, it will call Desk_Error2_Exit.
  202.  */
  203.  
  204.  
  205.  
  206. #define    Desk_Error2_Try        Desk_JumpAuto_Try
  207.  
  208. #define    Desk_Error2_Catch    Desk_JumpAuto_Catch
  209.  
  210. #define    Desk_Error2_EndCatch    Desk_JumpAuto_EndCatch
  211.  
  212. #define    Desk_Error2_TryCatch    Desk_JumpAuto_TryCatch
  213.  
  214.  
  215.  
  216. Desk_error2_block    *Desk_Error2_Exit( Desk_error2_block *error);
  217. /*
  218. Terminates program by calling Desk_Error_ReportFatal with a default error
  219. message.
  220.  
  221. Useful to do a 'Desk_Error2_SetHandler( Desk_Error_Exit) to garrantee any error
  222. will terminate the program with a message.
  223.  */
  224.  
  225. Desk_error2_block    *Desk_Error2_VerboseExit( Desk_error2_block *error);
  226. /*
  227. Useful for debugging / command-line programs. Uses Desk_Error_ReportFatal to
  228. give a description of the error that occurred.
  229.  
  230. Useful to do a 'Desk_Error2_SetHandler( Desk_Error_VerboseExit) to garrantee any
  231. error will terminate the program with a message.
  232.  
  233. Desk_Error2_VerboseExit only knows about the error types in the Desk_error2_type
  234. enum. Hence if you have your own error type, you should write your own
  235. verbose exit handler.
  236.  */
  237.  
  238.  
  239.  
  240.  
  241. typedef int    (*Desk_Error2_vprintf_fn)( void* reference, const char* format, va_list va);
  242. /*
  243. A function-type similar to vfprintf, except that the first parameter is
  244. a (void*).
  245.  */
  246.  
  247. typedef int    (*Desk_Error2_printf_fn)( void* reference, const char* format, ...);
  248. /*
  249. A function-type similar to fprintf, except that the first parameter is a
  250. (void*).
  251.  */
  252.  
  253. void    Desk_Error2_VDescribe( Desk_Error2_vprintf_fn fn, void* reference, const Desk_error2_block* error);
  254. /*
  255. Sends text about 'error' to 'fn', passing 'reference'.
  256.  */
  257.  
  258. void    Desk_Error2_FDescribe( Desk_Error2_printf_fn fn, void* reference, const Desk_error2_block* error);
  259. /*
  260. Sends text about 'error' to 'fn', passing 'reference'.
  261.  */
  262.  
  263. void    Desk_Error2_Describe( FILE* stream, const Desk_error2_block* error);
  264. /*
  265. Uses Desk_Error2_VDescribe to send info about 'error' to 'stream'.
  266.  */
  267.  
  268.  
  269.  
  270. typedef Desk_error2_block*    (*Desk_error2_handler)( Desk_error2_block *error);
  271. /*
  272. The type of a function which tries to handles errors - the function
  273. returns Desk_error2_HANDLED if succesfull. Use Desk_Error2_SetHandler to register
  274. such a handler function with Error2.
  275.  */
  276.  
  277. #define    Desk_error2_HANDLED (NULL)
  278. /*
  279. An Desk_error2_handler should return this if it has dealt with an error.
  280.  */
  281.  
  282.  
  283.  
  284. #define    Desk_Error2_SetHandler( handlerfn)    Desk_error2__handlerfn = (handlerfn)
  285. /*
  286. Sets the handler to be called by Desk_Error2_Handle.
  287. */
  288.  
  289. #define    Desk_Error2_GetHandler()    Desk_error2__handlerfn
  290. /*
  291. Returns the current handler.
  292.  */
  293.  
  294.  
  295.  
  296. int    Desk_Error2_GetNewErrorType( void);
  297. /*
  298. Returns a unique error number. Useful if an application (or part of an
  299. application) wants to have its own error type.
  300.  */
  301.  
  302.  
  303.  
  304. void    Desk_Error2_CheckOS( const Desk_os_error *error);
  305. /*
  306. A simple error-handler for use with functions which return an
  307. (Desk_os_error*). If error!=NULL, it sets up Desk_error2_globalblock
  308. appropriately for 'error', and calls Desk_Error2_Handle(
  309. Desk_error2_globalblock).
  310.  
  311. Use like:
  312.  
  313. Desk_Error2_CheckOS( _swix( ...);
  314.  
  315. When Desk_DEBUG is defined, Desk_Error2_CheckOS is macro-ed to
  316. Desk_Error2_CheckOS_Debug, which uses Desk_error_PLACE to output the
  317. place where the error occurred.
  318.  */
  319.  
  320.  
  321.  
  322.  
  323. void            Desk_Error2_CheckOS_Debug( const Desk_os_error *error, const char *place);
  324. /*
  325. Similar to Desk_Error2_CheckOS, except that it expects an extra string
  326. argument, for use with the Desk_DeskLib_DEBUG-version of Desk_Error2_CheckOS.
  327.  */
  328.  
  329.  
  330.  
  331. #if defined( Desk_DeskLib_DEBUG) && !defined( Desk__making_Error2)
  332.     
  333.     #define    Desk_Error2_CheckOS( oserror)    Desk_Error2_CheckOS_Debug( oserror, Desk_error_PLACE)
  334. /*
  335. This macro is defined for debugging purposes. It behaves in the same
  336. way, except that the 'text' field of Desk_error2_globalblock is set to
  337. Desk_error_PALCE, allowing an error-handler to display where the error came
  338. from.
  339.  */
  340. #endif
  341.  
  342.  
  343.  
  344. void    Desk_Error2_CheckBOOL( Desk_bool error);
  345. /*
  346. Calls Desk_Error2_Handle if error!=NOERROR.
  347. */
  348.  
  349.  
  350.  
  351. void    Desk_Error2_HandleText( const char* text);
  352. /*
  353. Sets up Desk_error2_globalblock to contain the text message and than calls
  354. Desk_Error2_Handle
  355.  */
  356.  
  357.  
  358. void    Desk_Error2_HandleTextf( const char* text, ...);
  359. /*
  360. Sets up Desk_error2_globalblock to contain the text message and than calls
  361. Desk_Error2_Handle. The text is specified as with printf.
  362.  
  363. Note that the text is sprintf-ed into an internal static 252-byte block,
  364. and no checking is done that it isn't too long.
  365.  */
  366.  
  367.  
  368.  
  369.  
  370. void    Desk_Error2_SignalHandler( int signalnumber);
  371. /*
  372. This function sets up Desk_error2_globalblock to contain information about
  373. the signal number 'signalnumber', and then calls Desk_Error2_Handle.
  374.  
  375. To use, register Desk_Error2_SignalHandler with the ANSI 'signal()' function
  376. for all the signals that you want to be treated with the Error2-library
  377. mechanism, eg:
  378.  
  379. int    main( void)
  380. {
  381. signal( SIGFPE,  &Desk_Error2_SignalHandler);
  382. ...
  383. }
  384.  
  385. Note that when a signal occurs, ANSI C resets signal handling for the
  386. signal. To get around this, when called, Desk_Error2_SignalHandler calls
  387. signal() to re-register itself for the specified signal.
  388.  
  389. You shouldn't call Desk_Error2_SignalHandler directly.
  390.  */
  391.  
  392.  
  393.  
  394. void    Desk_Error2_HandleAllSignals( void);
  395. /*
  396. This registers Desk_Error2_SignalHandler with signal() for all signals
  397. (SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM, SIGSTAK, SIGUSR1,
  398. SIGUSR2, SIGOSERROR).
  399.  
  400. This could be useful when debugging.
  401.  */
  402.  
  403.  
  404.  
  405. void    Desk_Error2_ClearErrorBlock( Desk_error2_block *error);
  406. /*
  407. Clears the various fields in 'error'. Useful when setting up an error
  408. block.
  409.  */
  410.  
  411. #ifdef Desk__using_SDLS
  412.     extern    Desk_error2_block*    Desk_Error2__Ref_globalblock( void);
  413.     extern    Desk_error2_handler*    Desk_Error2__Ref__handlerfn( void);
  414. #endif
  415.  
  416.  
  417. #if defined( Desk__using_SDLS) && !defined( Desk__making_Error2)
  418.  
  419.     #define    Desk_error2_globalblock    (*Desk_Error2__Ref_globalblock())
  420.     #define    Desk_error2__handlerfn    (*Desk_Error2__Ref__handlerfn())
  421.  
  422. #else
  423.  
  424.     extern    Desk_error2_block    Desk_Error2_globalblock;
  425. /*
  426. A global Desk_error2_block, for use by anyone. It is used by Desk_Error2_HandleOS
  427. etc.
  428.  */
  429.  
  430.     extern    Desk_error2_handler    Desk_error2__handlerfn;
  431. /*
  432. This is a global pointer to the function which is called by
  433. Desk_Error2_Handle. Use the macros Desk_Error2_SetHandler and
  434. Desk_Error2_GetHandler to access it.
  435.  
  436. Set to NULL initally.
  437.  */
  438.  
  439. #endif
  440.  
  441.  
  442.  
  443. #define    Desk_Error2_ReThrow()    Desk_Error2_Handle( &Desk_Error2_globalblock)
  444.  
  445.  
  446.  
  447. extern const char *Desk_Error2_signalnames[];
  448. /*
  449. Array of textual descriptions of signals.
  450.  */
  451.  
  452. void    Desk_Error2_ConvertToOS( Desk_os_error* oserror, Desk_error2_block* error2);
  453. /*
  454. Makes the os_error pointed to by 'oserror' contain info from 'error2'.
  455.  */
  456.  
  457.  
  458. #define    Desk_Error2_ConvertToOS2()    (Desk_Error2_ConvertToOS( &Desk_error_global, &Desk_Error2_globalblock), &Desk_error_global)
  459. /*
  460. Treat like:
  461. Desk_os_error*    Desk_Error2_ConvertToOS2( void);
  462.  
  463. Returns the current Desk_Error2 error converted to a (Desk_os_error*).
  464. Useful in functions which need to return a (os_error*) - eg:
  465.  
  466.  
  467. Desk_os_error*    Foo( ...)
  468.     {
  469.     Desk_Error2_Try    {
  470.         // Call various functions which might raise a Desk_Error2 error
  471.         }
  472.     Desk_Error2_Catch    {
  473.         // Clean up.
  474.         return Desk_Error2_ConvertToOS2();
  475.         }
  476.     Desk_Error2_EndCatch
  477.     return NULL;
  478.     }
  479.  
  480.  */
  481.  
  482.  
  483.  
  484.  
  485.  
  486.  
  487.  
  488.  
  489.  
  490.  
  491.  
  492.  
  493.  
  494. /*
  495. Error3
  496. ------
  497.  
  498. Error3 is an Desk_Event_-type library for registering handlers for different
  499. sorts of error. 
  500.  
  501. To use Error3, simply call Desk_Error3_UseError3() somwhere. This simply
  502. registers Desk_Error3__Dispatch as Error2's single error-handling function.
  503.  
  504. Desk_Error3__Dispatch looks for a previously-registered handler which matches
  505. the error, and calls it.
  506.  
  507. Hence any calls to Desk_Error2_Handle and Desk_Error2_XHandle (even those from
  508. within a previously-compiled library, such as DeskLib) will end up being
  509. dealt with by Error3's registered handler functions.
  510.  
  511. You shouldn't normally have to call Desk_Error3__Dispatch directly yourself -
  512. use Desk_Error2_Handle and Desk_Error2_XHandle.
  513.  
  514. Note that the Error3 calls are completely untested...
  515.  */
  516.  
  517.  
  518. #define    Desk_Error3_UseError3()    Desk_Error2_SetHandler( Desk_Error3__Dispatch);
  519. /*
  520. Makes all subsequent error handling by Desk_Error2_Handle and Desk_Error2_XHandle
  521. use the the Error3 system.
  522.  */
  523.  
  524.  
  525. typedef Desk_error2_block*    (*Desk_error3_handler)( Desk_error2_block *error, void *reference);
  526. /*
  527. The type of functions which can be registered with Desk_Error2_Claim* to
  528. handle errors. These functions should return Desk_error2_HANDLED if succesful.
  529.  */
  530.  
  531. /*void    Desk_Error3_ClaimFunction( Desk_error2_fnptr function, Desk_error3_handler handler, void *reference);
  532. *//*
  533. Register a handler to be called when an error is raised by 'function'. 
  534.  
  535. Function-specific handlers are checked before type-specific handlers
  536. (registered with Desk_Error3_ClaimType) and general handlers (registered with
  537. Desk_Error3_ClaimMisc).
  538.  
  539. New handlers are added to front of the list of handlers, so they are
  540. called in preference to any existing handlers.
  541.  */
  542.  
  543. void    Desk_Error3_ClaimType( Desk_error2_type type, Desk_error3_handler handler, void *reference);
  544. /*
  545. Register a handler to be called when an error of a particular type
  546. 'type' occurs. 
  547.  
  548. Type-specific handlers are checked after function-specific ones
  549. (registered with Desk_Error3_ClaimFunction), and before general handlers
  550. (registered with Desk_Error3_ClaimMisc).
  551.  
  552. New handlers are added to front of the list of handlers, so they are
  553. called in preference to any existing handlers.
  554.  */
  555.  
  556. void    Desk_Error3_ClaimMisc( Desk_error3_handler handler, void *reference);
  557. /*
  558. Register a misc handler to be called when any error occurs. 
  559.  
  560. Misc handlers are only checked after function-specific handlers
  561. (registered with Desk_Error3_ClaimFunction) and type-specific
  562. handlers (registered with Desk_Error3_ClaimType).
  563.  
  564. New handlers are added to front of the list of handlers, so they are
  565. called in preference to any existing handlers.
  566.  */
  567.  
  568.  
  569. /*void    Desk_Error3_ReleaseFunction( Desk_error2_fnptr function, Desk_error3_handler handler, void *reference);
  570. *//*
  571. Removes 'handler' from Error3's list of handlers. 'function' and
  572. 'reference' must be the same as in the call to Desk_Error3_ClaimFunction
  573. which registered 'handler'.
  574.  */
  575.  
  576. void    Desk_Error3_ReleaseType( Desk_error2_type type, Desk_error3_handler handler, void *reference);
  577. /*
  578. Removes 'handler' from Error3's list of handlers. 'type' and 'reference'
  579. must be the same as in the call to Desk_Error3_ClaimType which registered
  580. 'handler'.
  581.  */
  582.  
  583. void    Desk_Error3_ReleaseMisc( Desk_error3_handler handler, void *reference);
  584. /*
  585. Removes 'handler' from Error3's list of handlers. 'reference' must be
  586. the same as in the call to Desk_Error3_ClaimFunction which registered
  587. 'handler'.
  588.  */
  589.  
  590. Desk_error2_block*    Desk_Error3__Dispatch( Desk_error2_block* error, void* reference);
  591. /*
  592. Searches for and calls a suitable error-handler for error.
  593.  */
  594.  
  595.  
  596. #ifdef __cplusplus
  597. }
  598. #endif
  599.  
  600.  
  601. #endif
  602.