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 */
1.5.2