XLALError.h

Go to the documentation of this file.
00001 /*
00002 *  Copyright (C) 2007 Jolien Creighton, Kipp Cannon
00003 *
00004 *  This program is free software; you can redistribute it and/or modify
00005 *  it under the terms of the GNU General Public License as published by
00006 *  the Free Software Foundation; either version 2 of the License, or
00007 *  (at your option) any later version.
00008 *
00009 *  This program is distributed in the hope that it will be useful,
00010 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 *  GNU General Public License for more details.
00013 *
00014 *  You should have received a copy of the GNU General Public License
00015 *  along with with program; see the file COPYING. If not, write to the
00016 *  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00017 *  MA  02111-1307  USA
00018 */
00019 
00020 /** \file
00021  * \ingroup std
00022  * \author Creighton, J. D. E.
00023  * \date 2005
00024  * \brief This header covers routines to provide the XLAL interface error handling.
00025  *
00026  * \par XLAL Errors
00027  *
00028  * When an XLAL routine fails, the routine should set the <tt>xlalErrno</tt> to
00029  * an appropriate error number and return with the appropriate error code.  The
00030  * return value depends on the return type of the XLAL function.  Furthermore, the
00031  * XLAL error handler should be invoked.
00032  *
00033  * Whenever possible (i.e., always), standard XLAL error macros should be used
00034  * when generating an error.  These macros (i) invoke the current error handler,
00035  * (ii) set the error code to the specified value, and (iii) return with the
00036  * correct return value.  The error macros that should be used are:
00037  *
00038  * <tt>XLAL_ERROR(func,errnum)</tt> for XLAL routines returning an integer type.
00039  *
00040  * <tt>XLAL_ERROR_VOID(func,errnum)</tt> for XLAL routines with no return value.
00041  *
00042  * <tt>XLAL_ERROR_NULL(func,errnum)</tt> for XLAL routines returning a pointer.
00043  *
00044  * <tt>XLAL_ERROR_REAL4(func,errnum)</tt> for XLAL routines returning a <tt>REAL4</tt>
00045  * floating-point value.
00046  *
00047  * <tt>XLAL_ERROR_REAL8(func,errnum)</tt> for XLAL routines returning a <tt>REAL8</tt>
00048  * floating-point value.
00049  *
00050  * Additional error, warning, and informational messages can be generated using the
00051  * routines <tt>XLALPrintError()</tt>, <tt>XLALPrintWarning()</tt> and
00052  * <tt>XLALPrintInfo()</tt>.  These routines (which work just like <tt>printf()</tt>)
00053  * print or suppress the message depending on the value of <tt>lalDebugLevel</tt>.
00054  *
00055  * On rare occations, you may be prepared for an XLAL routine to fail, and may want
00056  * to handle the failure immediately.  In these circumstances, the XLAL error handler
00057  * needs to be disabled before the routine is called so that the failure can be
00058  * caught.  The <tt>XLAL_TRY(statement,errnum)</tt> macro is designed to be used in
00059  * these situations.  Here is an example:
00060  * \code
00061  * REAL8 XLALLogFactorial( INT4 n )
00062  * {
00063  *   REAL8 y;
00064  *   int errnum; 
00065  *   XLAL_TRY( y = XLALGammaFunction( n + 1 ), errnum );
00066  *   if ( XLAL_IS_REAL8_FAIL_NAN( y ) )
00067  *     switch ( errnum )
00068  *     {
00069  *       case XLAL_ERANGE:
00070  *         y  = n * ( log(n) - 1 );
00071  *         y += 0.5 * log( 2.0 * LAL_PI * n );
00072  *         return y;
00073  *       default:
00074  *         XLALSetErrno( errnum );
00075  *         XLAL_ERROR_REAL8( "XLALLogFactorial", XLAL_EFUNC );
00076  *     }
00077  *   return log( y );
00078  * }
00079  * \endcode
00080  *
00081  * \par XLAL Function Return Codes
00082  *
00083  * XLAL functions that return an integer-type will return <tt>XLAL_FAILURE</tt>
00084  * on failure.  XLAL functions that return a pointer will return <tt>NULL</tt>
00085  * on failure.
00086  *
00087  * The LAL specification requires that XLAL functions that return a
00088  * floating-point type (either <tt>REAL4</tt> or <tt>REAL8</tt>) should return a particular
00089  * value to indicate an error.  These values are given by the macros
00090  * <tt>XLAL_REAL4_FAIL_NAN</tt> and <tt>XLAL_REAL8_FAIL_NAN</tt> (they are Not a Number
00091  * or NaN values).  To implement these we choose hexadecimal representations
00092  * and then provide static functions that return the equivalent <tt>REAL4</tt> or
00093  * <tt>REAL8</tt> values.  The macros then invoke these functions.  This is done
00094  * so that the compiler can easily inline the functions (or eliminate them
00095  * if they are not used).  Conversion from the hexadecimal representation
00096  * to the floating-point representation is done using a union.
00097  *
00098  * The LAL specification also requires that there be two macros,
00099  * <tt>XLAL_IS_REAL4_FAIL_NAN(val)</tt> and <tt>XLAL_IS_REAL8_FAIL_NAN(val)</tt> that will
00100  * test if val is one of these XLAL-specific fail NaNs.  Again these macros
00101  * invoke static functions that return the result of the comparison.  The
00102  * cmparison itself is done with the hexadecimal representation.
00103  *
00104  * \par XLAL Error Codes
00105  *
00106  * The LAL specification requires particular return code and error values.
00107  * These are implemented here as enumeration constants in the <tt>XLALErrorValue</tt>
00108  * enumeration.
00109  *
00110  */
00111 
00112 #ifndef XLALERROR_H
00113 #define XLALERROR_H
00114 
00115 #include <stddef.h>
00116 #include <lal/LALAtomicDatatypes.h>
00117 
00118 NRCSID( XLALERRORH, "$Id: XLALError.h,v 1.14 2008/04/24 17:04:21 kipp Exp $" );
00119 
00120 #ifdef __cplusplus
00121 extern "C" {
00122 #pragma }
00123 #endif
00124 
00125 
00126 /*
00127  *
00128  * Use these functions to print arbitrary messages as errors or warnings.
00129  *
00130  */
00131 
00132 /** Prints an error message if error printing is enabled by lalDebugLevel. */
00133 int XLALPrintError( const char *fmt, ... );
00134 
00135 /** Prints a warning message if warning printing is enabled by lalDebugLevel. */
00136 int XLALPrintWarning( const char *fmt, ... );
00137 
00138 /** Prints an info message if info printing is enabled by lalDebugLevel. */
00139 int XLALPrintInfo( const char *fmt, ... );
00140 
00141 /** Prints a progress bar at the "info" verbosity level. */
00142 int XLALPrintProgressBar( double );
00143 
00144 /** Prints a deprecation warning at the "warning" verbosity level. */
00145 int XLALPrintDeprecationWarning( const char *old, const char *replacement );
00146 
00147 
00148 /* silence gcc warnings about certain (possibly) unused symbols */
00149 #ifdef __GNUC__
00150 #define UNUSED __attribute__ ((unused))
00151 #else
00152 #define UNUSED
00153 #endif
00154 
00155 /*
00156  *
00157  * The LAL specification requires that XLAL functions that return a
00158  * floating-point type (either <tt>REAL4</tt> or <tt>REAL8</tt>) should return a particular
00159  * value to indicate an error.  These values are given by the macros
00160  * <tt>XLAL_REAL4_FAIL_NAN</tt> and <tt>XLAL_REAL8_FAIL_NAN</tt> (they are Not a Number
00161  * or NaN values).  To implement these we choose hexadecimal representations
00162  * and then provide static functions that return the equivalent <tt>REAL4</tt> or
00163  * <tt>REAL8</tt> values.  The macros then invoke these functions.  This is done
00164  * so that the compiler can easily inline the functions (or eliminate them
00165  * if they are not used).  Conversion from the hexadecimal representation
00166  * to the floating-point representation is done using a union.
00167  *
00168  * The LAL specification also requires that there be two macros,
00169  * <tt>XLAL_IS_REAL4_FAIL_NAN(val)</tt> and <tt>XLAL_IS_REAL8_FAIL_NAN(val)</tt> that will
00170  * test if val is one of these XLAL-specific fail NaNs.  Again these macros
00171  * invoke static functions that return the result of the comparison.  The
00172  * cmparison itself is done with the hexadecimal representation.
00173  *
00174  */
00175 
00176 /* Hexadecimal representation of the <tt>REAL4</tt> and <tt>REAL8</tt> NaN failure bit pattern. */
00177 #define XLAL_REAL4_FAIL_NAN_INT 0x7fc001a1 /**< Hexadecimal representation of <tt>REAL4</tt> NaN failure bit pattern */
00178 #define XLAL_REAL8_FAIL_NAN_INT LAL_INT8_C(0x7ff80000000001a1) /**< Hexadecimal representation of <tt>REAL8</tt> NaN failure bit pattern */
00179 
00180 /*
00181  * The floating point values themselves are returned by static functions that
00182  * can be easily inlined by the compiler; similarly, the routines to test
00183  * if a value is the LAL failure NaN can also be inlined.
00184  */
00185 
00186 /** Returns the value of the XLAL <tt>REAL4</tt> failure NaN. */
00187 static REAL4 UNUSED XLALREAL4FailNaN( void )
00188 {
00189   volatile const union { INT4 i; REAL4 x; } val = { XLAL_REAL4_FAIL_NAN_INT } ;
00190   return val.x;
00191 }
00192 
00193 /** Returns the value of the XLAL <tt>REAL8</tt> failure NaN. */
00194 static REAL8 UNUSED XLALREAL8FailNaN( void )
00195 {
00196   volatile const union { INT8 i; REAL8 x; } val = { XLAL_REAL8_FAIL_NAN_INT } ;
00197   return val.x;
00198 }
00199 
00200 /** Tests if a value is an XLAL <tt>REAL4</tt> failure NaN. */
00201 static int UNUSED XLALIsREAL4FailNaN( REAL4 val )
00202 {
00203   volatile const union { INT4 i; unsigned char s[4]; } a = { XLAL_REAL4_FAIL_NAN_INT } ;
00204   volatile union { REAL4 x; unsigned char s[4]; } b;
00205   size_t n;
00206   b.x = val;
00207   for ( n = 0; n < sizeof( val ); ++n )
00208     if ( a.s[n] != b.s[n] )
00209       return 0;
00210   return 1;
00211 }
00212 
00213 /** Tests if a value is an XLAL <tt>REAL8</tt> failure NaN. */
00214 static int UNUSED XLALIsREAL8FailNaN( REAL8 val )
00215 {
00216   volatile const union { INT8 i; unsigned char s[8]; } a = { XLAL_REAL8_FAIL_NAN_INT } ;
00217   volatile union { REAL8 x; unsigned char s[8]; } b;
00218   size_t n;
00219   b.x = val;
00220   for ( n = 0; n < sizeof( val ); ++n )
00221     if ( a.s[n] != b.s[n] )
00222       return 0;
00223   return 1;
00224 }
00225 #undef UNUSED
00226 
00227 /* Here are the macro constants for the fail NaNs. */
00228 #define XLAL_REAL4_FAIL_NAN ( XLALREAL4FailNaN() ) /**< Floating-point value of the XLAL <tt>REAL4</tt> failure NaN. */
00229 #define XLAL_REAL8_FAIL_NAN ( XLALREAL8FailNaN() ) /**< Floating-point value of the XLAL <tt>REAL8</tt> failure NaN. */
00230 
00231 /* Here are the macros to test for fail NaNs. */
00232 #define XLAL_IS_REAL4_FAIL_NAN(val) XLALIsREAL4FailNaN(val) /**< Tests if <tt>val</tt> is a XLAL <tt>REAL4</tt> failure NaN. */
00233 #define XLAL_IS_REAL8_FAIL_NAN(val) XLALIsREAL8FailNaN(val) /**< Tests if <tt>val</tt> is a XLAL <tt>REAL8</tt> failure NaN. */
00234 
00235 
00236 
00237 /** XLAL error numbers and return values. */
00238 enum XLALErrorValue {
00239   XLAL_SUCCESS =  0, /**< Success return value (not an error number) */
00240   XLAL_FAILURE = -1, /**< Failure return value (not an error number) */
00241 
00242   /* these are standard error numbers */
00243   XLAL_EIO     =  5,  /**< I/O error */
00244   XLAL_ENOMEM  = 12,  /**< Memory allocation error */
00245   XLAL_EFAULT  = 14,  /**< Invalid pointer */
00246   XLAL_EINVAL  = 22,  /**< Invalid argument */
00247   XLAL_EDOM    = 33,  /**< Input domain error */
00248   XLAL_ERANGE  = 34,  /**< Output range error */
00249 
00250   /* extended error numbers start at 128 ... should be beyond normal errnos */
00251 
00252   /* these are common errors for XLAL functions */
00253   XLAL_EFAILED = 128, /**< Generic failure */
00254   XLAL_EBADLEN = 129, /**< Inconsistent or invalid length */
00255   XLAL_ESIZE   = 130, /**< Wrong size */
00256   XLAL_EDIMS   = 131, /**< Wrong dimensions */
00257   XLAL_ETYPE   = 132, /**< Wrong or unknown type */
00258   XLAL_ETIME   = 133, /**< Invalid time */
00259   XLAL_EFREQ   = 134, /**< Invalid freqency */
00260   XLAL_EUNIT   = 135, /**< Invalid units */
00261   XLAL_ENAME   = 136, /**< Wrong name */
00262   XLAL_EDATA   = 137, /**< Invalid data */
00263 
00264   /* user-defined errors */
00265   XLAL_EUSR0   = 200, /**< User-defined error 0 */
00266   XLAL_EUSR1   = 201, /**< User-defined error 1 */
00267   XLAL_EUSR2   = 202, /**< User-defined error 2 */
00268   XLAL_EUSR3   = 203, /**< User-defined error 3 */
00269   XLAL_EUSR4   = 204, /**< User-defined error 4 */
00270   XLAL_EUSR5   = 205, /**< User-defined error 5 */
00271   XLAL_EUSR6   = 206, /**< User-defined error 6 */
00272   XLAL_EUSR7   = 207, /**< User-defined error 7 */
00273   XLAL_EUSR8   = 208, /**< User-defined error 8 */
00274   XLAL_EUSR9   = 209, /**< User-defined error 9 */
00275 
00276   /* external or internal errors */
00277   XLAL_ESYS    = 254, /**< System error */
00278   XLAL_EERR    = 255, /**< Internal error */
00279 
00280   /* specific mathematical and numerical errors start at 256 */
00281 
00282   /* IEEE floating point errors */
00283   XLAL_EFPINVAL  = 256, /**< IEEE Invalid floating point operation, eg sqrt(-1), 0/0 */
00284   XLAL_EFPDIV0   = 257, /**< IEEE Division by zero floating point error */
00285   XLAL_EFPOVRFLW = 258, /**< IEEE Floating point overflow error */
00286   XLAL_EFPUNDFLW = 259, /**< IEEE Floating point underflow error */
00287   XLAL_EFPINEXCT = 260, /**< IEEE Floating point inexact error */
00288 
00289   /* numerical algorithm errors */
00290   XLAL_EMAXITER  = 261, /**< Exceeded maximum number of iterations */
00291   XLAL_EDIVERGE  = 262, /**< Series is diverging */
00292   XLAL_ESING     = 263, /**< Apparent singularity detected */
00293   XLAL_ETOL      = 264, /**< Failed to reach specified tolerance */
00294   XLAL_ELOSS     = 265, /**< Loss of accuracy */
00295 
00296   /* failure from within a function call: "or" error number with this */
00297   XLAL_EFUNC     = 1024 /**< Internal function call failed bit: "or" this with existing error number */
00298 };
00299 
00300 
00301 /*
00302  *
00303  * These functions provide message associated with an error code and print
00304  * an error message associated with the error code.  The macro XLAL_PERROR
00305  * fills in the current file and line information and uses the current
00306  * value of xlalErrno as the error number.
00307  *
00308  */
00309 
00310 /** Returns the error message associated with an error number. */
00311 const char * XLALErrorString( int errnum );
00312 
00313 /** Prints an error message for a particular error code in a standard format. */
00314 void XLALPerror( const char *func, const char *file, int line, int errnum );
00315 
00316 /** Prints an error message for the current value of <tt>xlalErrno</tt>. */
00317 #define XLAL_PERROR( func ) XLALPerror( func, __FILE__, __LINE__, xlalErrno )
00318 
00319 
00320 /*
00321  *
00322  * Here is the XLAL error handler type and the routines that set it.
00323  * Also provide is the default error handler.
00324  *
00325  */
00326 
00327 /** The XLAL error handler type. */
00328 typedef void XLALErrorHandlerType( const char *func, const char *file, int line, int errnum ); 
00329 
00330 /** The default XLAL error handler. */
00331 void XLALDefaultErrorHandler( const char *func, const char *file, int line, int errnum );
00332 /** A silent XLAL error handler. */
00333 void XLALSilentErrorHandler( const char *func, const char *file, int line, int errnum );
00334 
00335 /* Other useful XLAL error handlers. */
00336 /** The XLAL error handler that raises SIGABRT. */
00337 void XLALAbortErrorHandler( const char *func, const char *file, int line, int errnum );
00338 /** The XLAL error handler that calls exit. */
00339 void XLALExitErrorHandler( const char *func, const char *file, int line, int errnum );
00340 /** The XLAL error handler that prints a function call backtrace then raises SIGABRT. */
00341 void XLALBacktraceErrorHandler( const char *func, const char *file, int line, int errnum );
00342 
00343 
00344 
00345 /** Sets the error handler to a new handler and returns the old handler. */
00346 XLALErrorHandlerType * XLALSetErrorHandler( XLALErrorHandlerType *newHandler );
00347 
00348 /** Sets the error handler to the default handler and returns the old handler. */
00349 XLALErrorHandlerType * XLALSetDefaultErrorHandler( void );
00350 /** Sets the error handler to a silent handler and returns the old handler. */
00351 XLALErrorHandlerType * XLALSetSilentErrorHandler( void );
00352 
00353 
00354 /*
00355  *
00356  * Here are the routines that set or clear the XLAL error number.
00357  *
00358  */
00359 
00360 /** Sets the XLAL error number to errnum, returns the new value. */
00361 int XLALSetErrno( int errnum );
00362 
00363 /** Gets the XLAL base error number ignoring the internal-function-failed flag. */
00364 int XLALGetBaseErrno( void );
00365 
00366 /** Clears the XLAL error number, returns the old value. */
00367 int XLALClearErrno( void );
00368 
00369 /*
00370  *
00371  * The LAL specifiation requires that the XLAL error number be a modifiable
00372  * lvalue.  Similarly, the function pointer to the XLAL error handler is
00373  * a modifiable lvalue.  These are implemented as macros that dereference
00374  * pointers to the current value (in the current thread).  The pointer is
00375  * returned by the functions XLALGetErrnoPtr and XLALGetErrorHandlerPtr.
00376  * Here these functions and macros are defined.
00377  *
00378  */
00379 
00380 /** Function to return pointer to the XLAL error number. */
00381 int * XLALGetErrnoPtr( void );
00382 
00383 /** Function to return pointer to the XLAL error handler function pointer. */
00384 XLALErrorHandlerType ** XLALGetErrorHandlerPtr( void );
00385 
00386 /* these are the modifiable lvalues for xlalErrno and XLALErrorHandler */
00387 #define xlalErrno ( * XLALGetErrnoPtr() ) /**< Modifiable lvalue containing the XLAL error number */
00388 #define XLALErrorHandler ( * XLALGetErrorHandlerPtr() ) /**< Modifiable lvalue containing the XLAL error handler */
00389 
00390 
00391 /**
00392  *
00393  * A macro to (i) disable the XLAL error handling and preserve the
00394  * current value of xlalErrno (ii) perform a statement that involves an
00395  * XLAL function call and (iii) restore the XLAL error handler and value of
00396  * xlalErrno while setting variable errnum to the xlalErrno set by the
00397  * statement.
00398  *
00399  */
00400 #define XLAL_TRY( statement, errnum ) \
00401         do { \
00402           XLALErrorHandlerType *xlalSaveErrorHandler; \
00403           int xlalSaveErrno; \
00404           xlalSaveErrorHandler = XLALSetSilentErrorHandler(); \
00405           xlalSaveErrno = xlalErrno; \
00406           XLALClearErrno(); \
00407           statement ; \
00408           errnum = xlalErrno; \
00409           xlalErrno = xlalSaveErrno; \
00410           XLALSetErrorHandler( xlalSaveErrorHandler ); \
00411         } while ( 0 )
00412 
00413 
00414 /*
00415  *
00416  * Here are the routines and macros that are used to report errors when
00417  * an XLAL function fails.  They (i) set the XLAL error number and (ii)
00418  * invoke the XLAL error handler.  The macros also (iii) return the
00419  * appropriate failure codes.  The macros should be used to report all
00420  * failures.
00421  *
00422  */
00423 
00424 /** Routine to set the XLAL error number and invoke the XLAL error handler.
00425  * It is used by the error macros. */
00426 void XLALError(
00427     const char *func, /**< name of function where the error occurs */
00428     const char *file, /**< source file name (use the __FILE__ macro) */
00429     int line,         /**< source line number (use the __LINE__ macro) */
00430     int errnum        /**< error code */
00431     );
00432 
00433 /** Macro to invoke the <tt>XLALError()</tt> function and return with code val (it should not
00434  * really be used itself, but forms the basis for other macros). */
00435 #define XLAL_ERROR_VAL( func, errnum, val ) \
00436         do { \
00437           XLALError( func, __FILE__, __LINE__, errnum ); \
00438           return val; \
00439         } while (0)
00440 
00441 /** Macro to invoke a failure from a XLAL routine returning an integer. */
00442 #define XLAL_ERROR( func, errnum ) \
00443     XLAL_ERROR_VAL( func, errnum, XLAL_FAILURE )
00444 
00445 /** Macro to invoke a failure from a XLAL routine returning a pointer. */
00446 #define XLAL_ERROR_NULL( func, errnum ) \
00447     XLAL_ERROR_VAL( func, errnum, NULL )
00448 
00449 /** Macro to invoke a failure from a XLAL routine returning void. */
00450 #define XLAL_ERROR_VOID( func, errnum ) \
00451     XLAL_ERROR_VAL( func, errnum, /* void */ )
00452 
00453 /** Macro to invoke a failure from a XLAL routine returning a <tt>REAL4</tt> */
00454 #define XLAL_ERROR_REAL4( func, errnum ) \
00455     XLAL_ERROR_VAL( func, errnum, XLAL_REAL4_FAIL_NAN )
00456 
00457 /** Macro to invoke a failure from a XLAL routine returning a <tt>REAL8</tt> */
00458 #define XLAL_ERROR_REAL8( func, errnum ) \
00459     XLAL_ERROR_VAL( func, errnum, XLAL_REAL8_FAIL_NAN )
00460 
00461 #ifdef __cplusplus
00462 #pragma {
00463 }
00464 #endif
00465 
00466 #endif /* XLALERROR_H */

Generated on Tue Oct 14 02:32:38 2008 for LAL by  doxygen 1.5.2