XLALError.c

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 $Date: 2008/04/24 17:04:21 $
00024  * \brief Standard XLAL error routines.
00025  *
00026  * $Id: XLALError.c,v 1.13 2008/04/24 17:04:21 kipp Exp $
00027  */
00028 
00029 #include <math.h>
00030 #include <stdio.h>
00031 #include <stdarg.h>
00032 #include <stdlib.h>
00033 #include <lal/XLALError.h>
00034 #include <lal/LALStdlib.h>
00035 
00036 NRCSID( XLALERRORC, "$Id: XLALError.c,v 1.13 2008/04/24 17:04:21 kipp Exp $" );
00037 
00038 /*
00039  *
00040  * Routines to print generic error messages and warning messages.
00041  *
00042  */
00043 
00044 /** Prints an error message if error printing is enabled by lalDebugLevel. */
00045 int XLALPrintError( const char *fmt, ... )
00046 {
00047   int n = 0;
00048   if ( lalDebugLevel & LALERROR )
00049   {
00050     va_list ap;
00051     va_start( ap, fmt );
00052     n = vfprintf( stderr, fmt, ap );
00053     va_end( ap );
00054   }
00055   return n;
00056 }
00057 
00058 /** Prints a warning message if warning printing is enabled by lalDebugLevel. */
00059 int XLALPrintWarning( const char *fmt, ... )
00060 {
00061   int n = 0;
00062   if ( lalDebugLevel & LALWARNING )
00063   {
00064     va_list ap;
00065     va_start( ap, fmt );
00066     n = vfprintf( stderr, fmt, ap );
00067     va_end( ap );
00068   }
00069   return n;
00070 }
00071 
00072 /** Prints an info message if info printing is enabled by lalDebugLevel. */
00073 int XLALPrintInfo( const char *fmt, ... )
00074 {
00075   int n = 0;
00076   if ( lalDebugLevel & LALINFO )
00077   {
00078     va_list ap;
00079     va_start( ap, fmt );
00080     n = vfprintf( stderr, fmt, ap );
00081     va_end( ap );
00082   }
00083   return n;
00084 }
00085 
00086 /**
00087  * Prints a progress bar at the "info" verbosity level.
00088  */
00089 
00090 int XLALPrintProgressBar( double fraction )
00091 {
00092   static const char mrk[] = "+++++++++++++++++++++++++++++++++++++++++++++++++)";
00093   static const char spc[] = "-------------------------------------------------)";
00094   int l = sizeof(mrk)/sizeof(*mrk) - 1;
00095   int offset = floor((fraction < 0.0 ? 0.0 : fraction > 1.0 ? 1.0 : fraction) * l + 0.5);
00096 
00097   return XLALPrintInfo("[%s%s %.1f%%", mrk + l - offset, spc + offset, 100.0 * fraction);
00098 }
00099 
00100 /**
00101  * Prints a deprecation warning at the "warning" verbosity level.
00102  */
00103 
00104 int XLALPrintDeprecationWarning( const char *old, const char *replacement )
00105 {
00106   return XLALPrintWarning("DEPRECATION WARNING:  program has invoked obsolete function %s().  Please see %s() for information about a replacement.\n", old, replacement);
00107 }
00108 
00109 
00110 /*
00111  *
00112  * Implementation of xlalErrno and XLALErrorHandler.
00113  * If code must be POSIX thread safe then the code is somewhat more complicated.
00114  *
00115  */
00116 
00117 #ifndef LAL_PTHREAD_LOCK /* non-pthread-safe code */
00118 
00119 /* XLAL error number is just a global variable */
00120 int xlalErrnoGlobal = 0;
00121 
00122 /* XLALGetErrnoPtr just returns the address of the global variable */
00123 int * XLALGetErrnoPtr( void )
00124 {
00125   return &xlalErrnoGlobal;
00126 }
00127 
00128 /* XLAL error handler is just a global variable */
00129 XLALErrorHandlerType *xlalErrorHandlerGlobal = NULL;
00130 
00131 /* XLALGetErrorHandlerPtr just returns the address of the global variable */
00132 XLALErrorHandlerType ** XLALGetErrorHandlerPtr( void )
00133 {
00134   return &xlalErrorHandlerGlobal;
00135 }
00136 
00137 #else  /* pthread safe code */
00138 
00139 /* Note: malloc and free are used here rather than LALMalloc and LALFree...
00140  * this is so that if a user checks for memory leaks within a thread before
00141  * rejoining to the main thread (which shouldn't be done) then at least
00142  * these routines won't report any leaks.  */
00143 
00144 #include <unistd.h>
00145 #include <pthread.h>
00146 
00147 pthread_key_t   xlalErrnoKey;
00148 pthread_once_t  xlalErrnoKeyOnce = PTHREAD_ONCE_INIT;
00149 pthread_key_t   xlalErrorHandlerKey;
00150 pthread_once_t  xlalErrorHandlerKeyOnce = PTHREAD_ONCE_INIT;
00151 
00152 /* routine to free the XLAL error number pointer */
00153 static void XLALDestroyErrnoPtr( void *xlalErrnoPtr )
00154 {
00155   free( xlalErrnoPtr );
00156   return;
00157 }
00158 
00159 /* routine to free the XLAL error handler pointer */
00160 static void XLALDestroyErrorHandlerPtr( void *xlalErrorHandlerPtr )
00161 {
00162   free( xlalErrorHandlerPtr );
00163   return;
00164 }
00165 
00166 /* routine to create the XLAL error number key */
00167 static void XLALCreateErrnoKey( void )
00168 {
00169   pthread_key_create( &xlalErrnoKey, XLALDestroyErrnoPtr );
00170   return;
00171 }
00172 
00173 /* routine to create the XLAL error handler key */
00174 static void XLALCreateErrorHandlerKey( void )
00175 {
00176   pthread_key_create( &xlalErrorHandlerKey, XLALDestroyErrorHandlerPtr );
00177   return;
00178 }
00179 
00180 /* return the pointer to the XLAL error number in this thread */
00181 int * XLALGetErrnoPtr( void )
00182 {
00183   int *xlalErrnoPtr;
00184 
00185   /* create key on the first call only */
00186   pthread_once( &xlalErrnoKeyOnce, XLALCreateErrnoKey );
00187 
00188   /* get the pointer to the XLAL error number in this thread */
00189   xlalErrnoPtr = pthread_getspecific( xlalErrnoKey ); 
00190   if ( ! xlalErrnoPtr ) /* haven't allocated pointer yet... do it now */
00191   {
00192     xlalErrnoPtr  = malloc( sizeof( *xlalErrnoPtr ) );
00193     if ( ! xlalErrnoPtr )
00194       lalAbortHook( "could not set xlal error number: malloc failed\n" );
00195     *xlalErrnoPtr = 0; /* raises segv if memory allocation fails */
00196     /* now set the value of the pointer in this thread in the key */
00197     if ( pthread_setspecific( xlalErrnoKey, xlalErrnoPtr ) )
00198       lalAbortHook( "could not set xlal error number: pthread_setspecific failed\n" );
00199   }
00200   return xlalErrnoPtr;
00201 }
00202 
00203 /* return the pointer to the XLAL error handler in this thread */
00204 XLALErrorHandlerType ** XLALGetErrorHandlerPtr( void )
00205 {
00206   XLALErrorHandlerType **xlalErrorHandlerPtr;
00207 
00208   /* create key on the first call only */
00209   pthread_once( &xlalErrorHandlerKeyOnce, XLALCreateErrorHandlerKey );
00210 
00211   /* get the pointer to the XLAL error handler in this thread */
00212   xlalErrorHandlerPtr = pthread_getspecific( xlalErrorHandlerKey );
00213   if ( ! xlalErrorHandlerPtr ) /* haven't allocated pointer yet... do it now */
00214   {
00215     xlalErrorHandlerPtr  = malloc( sizeof( *xlalErrorHandlerPtr ) );
00216     if ( ! xlalErrorHandlerPtr )
00217       lalAbortHook( "could not set xlal error handler: malloc failed\n" );
00218     *xlalErrorHandlerPtr = NULL; /* raises segv if memory allocation fails */
00219     /* now set the value of the pointer in this thread in the key */
00220     if ( pthread_setspecific( xlalErrorHandlerKey, xlalErrorHandlerPtr ) )
00221       lalAbortHook( "could not set xlal error handler: pthread_setspecific failed\n" );
00222   }
00223   return xlalErrorHandlerPtr;
00224 }
00225 
00226 #endif /* end of pthread-safe code */
00227 
00228 
00229 /*
00230  *
00231  * Here are the routines to set the error number or error handler.
00232  *
00233  */
00234 
00235 
00236 /** Set the XLAL error number to errnum. */
00237 int XLALSetErrno( int errnum )
00238 {
00239   if ( errnum == 0 )
00240   {
00241     xlalErrno = 0;
00242     return xlalErrno;
00243   }
00244 
00245   /* if this is an error indicating an internal error then set the bit
00246    * that indicates this; otherwise, xlalErrno should presumably be zero */
00247   if ( errnum & XLAL_EFUNC )
00248   {
00249     xlalErrno |= XLAL_EFUNC; /* make sure XLAL_EFUNC bit is set */
00250     return xlalErrno;
00251   }
00252 
00253   /* if xlalErrno is not zero, probably forgot to deal with previous error */
00254   if ( xlalErrno ) 
00255     XLALPrintWarning( "XLAL Warning - XLALSetErrno: "
00256         "Ignoring previous error (xlalErrno=%d) %s\n",
00257         xlalErrno, XLALErrorString( xlalErrno ) );
00258   xlalErrno = errnum;
00259   return xlalErrno;
00260 }
00261 
00262 
00263 /** Gets the basic error number ignoring the internal-function-failed flag. */
00264 int XLALGetBaseErrno( void )
00265 {
00266   return xlalErrno & ~XLAL_EFUNC;
00267 }
00268 
00269 
00270 /** Clears the XLAL error number. */
00271 int XLALClearErrno( void )
00272 {
00273   int olderrno = xlalErrno;
00274   xlalErrno = 0;
00275   return olderrno;
00276 }
00277 
00278 
00279 /** Set the XLAL error handler to newHandler; return the old handler. */
00280 XLALErrorHandlerType * XLALSetErrorHandler( XLALErrorHandlerType *newHandler )
00281 {
00282   XLALErrorHandlerType *oldHandler;
00283   oldHandler = XLALErrorHandler;
00284   XLALErrorHandler = newHandler;
00285   return oldHandler;
00286 }
00287 
00288 
00289 /** Set the XLAL error handler to the default handler; return the old handler. */
00290 XLALErrorHandlerType * XLALSetDefaultErrorHandler( void )
00291 {
00292   XLALErrorHandlerType *oldHandler;
00293   oldHandler = XLALErrorHandler;
00294   XLALErrorHandler = XLALDefaultErrorHandler;
00295   return oldHandler;
00296 }
00297 
00298 /** Set the XLAL error handler to a silent handler; return the old handler. */
00299 XLALErrorHandlerType * XLALSetSilentErrorHandler( void )
00300 {
00301   XLALErrorHandlerType *oldHandler;
00302   oldHandler = XLALErrorHandler;
00303   XLALErrorHandler = XLALSilentErrorHandler;
00304   return oldHandler;
00305 }
00306 
00307 
00308 /*
00309  *
00310  * Routines to give the error message associated with a given error number.
00311  *
00312  */
00313 
00314 
00315 /** Return the error message associated with an error number or return value. */
00316 const char * XLALErrorString( int code )
00317 {
00318 
00319   if ( code <= 0 ) /* this is a return code, not an error number */
00320   {
00321     if ( code == 0 )
00322       return "Success";
00323     else if ( code == -1 )
00324       return "Failure";
00325     else
00326       return "Unknown return code";
00327   }
00328 
00329   /* check to see if an internal function call has failed, but the error
00330    * number was not "or"ed against the mask XLAL_EFUNC */
00331   if ( code == XLAL_EFUNC ) 
00332     return "Internal function call failed";
00333 
00334   /* use this to report error strings... deals with possible mask for errors
00335    * arising from internal function calls */
00336 # define XLAL_ERROR_STRING(s) \
00337     ( ( code & XLAL_EFUNC ) ? "Internal function call failed: " s : s )
00338   switch ( code & ~XLAL_EFUNC )
00339   {
00340     /* these are standard error numbers */
00341     case XLAL_EIO:
00342       return XLAL_ERROR_STRING( "I/O error" );
00343     case XLAL_ENOMEM:
00344       return XLAL_ERROR_STRING( "Memory allocation error" );
00345     case XLAL_EFAULT:
00346       return XLAL_ERROR_STRING( "Invalid pointer" );
00347     case XLAL_EINVAL:
00348       return XLAL_ERROR_STRING( "Invalid argument" );
00349     case XLAL_EDOM:
00350       return XLAL_ERROR_STRING( "Input domain error" );
00351     case XLAL_ERANGE:
00352       return XLAL_ERROR_STRING( "Output range error" );
00353 
00354     /* extended error numbers start at 128 ... should be beyond normal errnos */
00355 
00356     /* these are common errors for XLAL functions */
00357     case XLAL_EFAILED:
00358       return XLAL_ERROR_STRING( "Generic failure" );
00359     case XLAL_EBADLEN:
00360       return XLAL_ERROR_STRING( "Inconsistent or invalid vector length" );
00361     case XLAL_ESIZE:
00362       return XLAL_ERROR_STRING( "Wrong size" );
00363     case XLAL_EDIMS:
00364       return XLAL_ERROR_STRING( "Wrong dimensions" );
00365     case XLAL_ETYPE:
00366       return XLAL_ERROR_STRING( "Wrong or unknown type" );
00367     case XLAL_ETIME:
00368       return XLAL_ERROR_STRING( "Invalid time" );
00369     case XLAL_EFREQ:
00370       return XLAL_ERROR_STRING( "Invalid freqency" );
00371     case XLAL_EUNIT:
00372       return XLAL_ERROR_STRING( "Invalid units" );
00373     case XLAL_ENAME:
00374       return XLAL_ERROR_STRING( "Wrong name" );
00375     case XLAL_EDATA:
00376       return XLAL_ERROR_STRING( "Invalid data" );
00377 
00378     /* user-defined errors */
00379     case XLAL_EUSR0:
00380       return XLAL_ERROR_STRING( "User-defined error 0" );
00381     case XLAL_EUSR1:
00382       return XLAL_ERROR_STRING( "User-defined error 1" );
00383     case XLAL_EUSR2:
00384       return XLAL_ERROR_STRING( "User-defined error 2" );
00385     case XLAL_EUSR3:
00386       return XLAL_ERROR_STRING( "User-defined error 3" );
00387     case XLAL_EUSR4:
00388       return XLAL_ERROR_STRING( "User-defined error 4" );
00389     case XLAL_EUSR5:
00390       return XLAL_ERROR_STRING( "User-defined error 5" );
00391     case XLAL_EUSR6:
00392       return XLAL_ERROR_STRING( "User-defined error 6" );
00393     case XLAL_EUSR7:
00394       return XLAL_ERROR_STRING( "User-defined error 7" );
00395     case XLAL_EUSR8:
00396       return XLAL_ERROR_STRING( "User-defined error 8" );
00397     case XLAL_EUSR9:
00398       return XLAL_ERROR_STRING( "User-defined error 9" );
00399 
00400   /* external or internal errors */
00401     case XLAL_ESYS:
00402       return XLAL_ERROR_STRING( "System error" );
00403     case XLAL_EERR:
00404       return XLAL_ERROR_STRING( "Internal error" );
00405 
00406     /* specific mathematical and numerical errors start at 256 */
00407 
00408     /* IEEE floating point errors */
00409     case XLAL_EFPINVAL:
00410       return XLAL_ERROR_STRING( "Invalid floating point operation, eg sqrt(-1), 0/0" );
00411     case XLAL_EFPDIV0:
00412       return XLAL_ERROR_STRING( "Division by zero floating point error" );
00413     case XLAL_EFPOVRFLW:
00414       return XLAL_ERROR_STRING( "Floating point overflow error" );
00415     case XLAL_EFPUNDFLW:
00416       return XLAL_ERROR_STRING( "Floating point underflow error" );
00417     case XLAL_EFPINEXCT:
00418       return XLAL_ERROR_STRING( "Floating point inexact error" );
00419 
00420     /* numerical algorithm errors */
00421     case XLAL_EMAXITER:
00422       return XLAL_ERROR_STRING( "Exceeded maximum number of iterations" );
00423     case XLAL_EDIVERGE:
00424       return XLAL_ERROR_STRING( "Series is diverging" );
00425     case XLAL_ESING:
00426       return XLAL_ERROR_STRING( "Apparent singularity detected" );
00427     case XLAL_ETOL:
00428       return XLAL_ERROR_STRING( "Failed to reach specified tolerance" );
00429     case XLAL_ELOSS:
00430       return XLAL_ERROR_STRING( "Loss of accuracy" );
00431 
00432     /* unrecognized error number */
00433     default:
00434       return "Unknown error";
00435   }
00436 # undef XLAL_ERROR_STRING
00437   return NULL; /* impossible to get here */
00438 }
00439 
00440 /** Print an error message associated with an error number or return code. */
00441 void XLALPerror( const char *func, const char *file, int line, int code )
00442 {
00443   if ( code > 0 )
00444     XLALPrintError( "XLAL Error" );
00445   else
00446     XLALPrintError( "XLAL Result" );
00447   if ( func && *func )
00448     XLALPrintError( " - %s", func );
00449   if ( file && *file )
00450     XLALPrintError( " (%s:%d)", file, line );
00451   XLALPrintError( ": " );
00452   XLALPrintError( XLALErrorString( code ) );
00453   XLALPrintError( "\n" );
00454   return;
00455 }
00456 
00457 
00458 /*
00459  *
00460  * Here is the default error handler.
00461  *
00462  */
00463 
00464 /** Default XLAL error handler */
00465 void XLALDefaultErrorHandler( const char *func, const char *file, int line, int errnum )
00466 {
00467   XLALPerror( func, file, line, errnum );
00468   return;
00469 }
00470 
00471 /** Silent XLAL error handler */
00472 void XLALSilentErrorHandler( const char *func, const char *file, int line, int errnum )
00473 {
00474   func = NULL;
00475   file = NULL;
00476   line = 0;
00477   errnum = 0;
00478   return;
00479 }
00480 
00481 
00482 /**
00483  *
00484  * Routine to set the error number and invoke the current error handler.
00485  *
00486  */
00487 void XLALError( const char *func, const char *file, int line, int errnum )
00488 {
00489   XLALSetErrno( errnum );
00490   if ( ! XLALErrorHandler )
00491     XLALErrorHandler = XLALDefaultErrorHandler;
00492   XLALErrorHandler( func, file, line, xlalErrno );
00493   return;
00494 }
00495 
00496 
00497 /*
00498  *
00499  * Useful standard error handlers
00500  *
00501  */
00502 
00503 /** XLAL error handler to abort on error. */
00504 void XLALAbortErrorHandler( const char *func, const char *file, int line,
00505     int errnum )
00506 {
00507   XLALPerror( func, file, line, errnum );
00508   abort();
00509 }
00510 
00511 /** XLAL error handler to exit on error. */
00512 void XLALExitErrorHandler( const char *func, const char *file, int line,
00513     int errnum )
00514 {
00515   XLALPerror( func, file, line, errnum );
00516   exit(1);
00517 }
00518 
00519 static int print_stack(void);
00520 /** XLAL error handler to abort on error and print a backtrace (if possible). */
00521 void XLALBacktraceErrorHandler( const char *func, const char *file, int line,
00522     int errnum )
00523 {
00524   XLALPerror( func, file, line, errnum );
00525   print_stack();
00526   abort();
00527 }
00528 
00529 /*
00530  * Internal routine to print call list.
00531  * Requires GCC.
00532  */
00533 
00534 #ifdef __GNUC__
00535 
00536 #if defined(__DARWIN_UNIX03) || defined(__GLIBC__)
00537 
00538 #define LEVELMAX 0100
00539 
00540 #if defined(__GLIBC__)
00541 
00542 /* Using GLIBC: there is a backtrace function avaliable */
00543 #include <execinfo.h>
00544 
00545 static int print_stack( void )
00546 {
00547   void *array[LEVELMAX];
00548   size_t size;
00549   size = backtrace( array, LEVELMAX );
00550   fprintf( stderr, "Call list:\n" );
00551   backtrace_symbols_fd( array, size, fileno( stderr ) );
00552   return 0;
00553 }
00554 
00555 #else
00556 
00557 
00558 /* Using DARWIN_UNIX03 */
00559 
00560 #ifdef __GLIBC__
00561 #define __USE_GNU /* required to get dladdr */
00562 #endif
00563 #include <dlfcn.h>
00564 
00565 #define get_return_address(addr,level) \
00566   do switch (level) { \
00567     case 000: addr = __builtin_frame_address(000) ? __builtin_return_address(000) : NULL; break; \
00568     case 001: addr = __builtin_frame_address(001) ? __builtin_return_address(001) : NULL; break; \
00569     case 002: addr = __builtin_frame_address(002) ? __builtin_return_address(002) : NULL; break; \
00570     case 003: addr = __builtin_frame_address(003) ? __builtin_return_address(003) : NULL; break; \
00571     case 004: addr = __builtin_frame_address(004) ? __builtin_return_address(004) : NULL; break; \
00572     case 005: addr = __builtin_frame_address(005) ? __builtin_return_address(005) : NULL; break; \
00573     case 006: addr = __builtin_frame_address(006) ? __builtin_return_address(006) : NULL; break; \
00574     case 007: addr = __builtin_frame_address(007) ? __builtin_return_address(007) : NULL; break; \
00575     case 010: addr = __builtin_frame_address(010) ? __builtin_return_address(010) : NULL; break; \
00576     case 011: addr = __builtin_frame_address(011) ? __builtin_return_address(011) : NULL; break; \
00577     case 012: addr = __builtin_frame_address(012) ? __builtin_return_address(012) : NULL; break; \
00578     case 013: addr = __builtin_frame_address(013) ? __builtin_return_address(013) : NULL; break; \
00579     case 014: addr = __builtin_frame_address(014) ? __builtin_return_address(014) : NULL; break; \
00580     case 015: addr = __builtin_frame_address(015) ? __builtin_return_address(015) : NULL; break; \
00581     case 016: addr = __builtin_frame_address(016) ? __builtin_return_address(016) : NULL; break; \
00582     case 017: addr = __builtin_frame_address(017) ? __builtin_return_address(017) : NULL; break; \
00583     case 020: addr = __builtin_frame_address(020) ? __builtin_return_address(020) : NULL; break; \
00584     case 021: addr = __builtin_frame_address(021) ? __builtin_return_address(021) : NULL; break; \
00585     case 022: addr = __builtin_frame_address(022) ? __builtin_return_address(022) : NULL; break; \
00586     case 023: addr = __builtin_frame_address(023) ? __builtin_return_address(023) : NULL; break; \
00587     case 024: addr = __builtin_frame_address(024) ? __builtin_return_address(024) : NULL; break; \
00588     case 025: addr = __builtin_frame_address(025) ? __builtin_return_address(025) : NULL; break; \
00589     case 026: addr = __builtin_frame_address(026) ? __builtin_return_address(026) : NULL; break; \
00590     case 027: addr = __builtin_frame_address(027) ? __builtin_return_address(027) : NULL; break; \
00591     case 030: addr = __builtin_frame_address(030) ? __builtin_return_address(030) : NULL; break; \
00592     case 031: addr = __builtin_frame_address(031) ? __builtin_return_address(031) : NULL; break; \
00593     case 032: addr = __builtin_frame_address(032) ? __builtin_return_address(032) : NULL; break; \
00594     case 033: addr = __builtin_frame_address(033) ? __builtin_return_address(033) : NULL; break; \
00595     case 034: addr = __builtin_frame_address(034) ? __builtin_return_address(034) : NULL; break; \
00596     case 035: addr = __builtin_frame_address(035) ? __builtin_return_address(035) : NULL; break; \
00597     case 036: addr = __builtin_frame_address(036) ? __builtin_return_address(036) : NULL; break; \
00598     case 037: addr = __builtin_frame_address(037) ? __builtin_return_address(037) : NULL; break; \
00599     case 040: addr = __builtin_frame_address(040) ? __builtin_return_address(040) : NULL; break; \
00600     case 041: addr = __builtin_frame_address(041) ? __builtin_return_address(041) : NULL; break; \
00601     case 042: addr = __builtin_frame_address(042) ? __builtin_return_address(042) : NULL; break; \
00602     case 043: addr = __builtin_frame_address(043) ? __builtin_return_address(043) : NULL; break; \
00603     case 044: addr = __builtin_frame_address(044) ? __builtin_return_address(044) : NULL; break; \
00604     case 045: addr = __builtin_frame_address(045) ? __builtin_return_address(045) : NULL; break; \
00605     case 046: addr = __builtin_frame_address(046) ? __builtin_return_address(046) : NULL; break; \
00606     case 047: addr = __builtin_frame_address(047) ? __builtin_return_address(047) : NULL; break; \
00607     case 050: addr = __builtin_frame_address(050) ? __builtin_return_address(050) : NULL; break; \
00608     case 051: addr = __builtin_frame_address(051) ? __builtin_return_address(051) : NULL; break; \
00609     case 052: addr = __builtin_frame_address(052) ? __builtin_return_address(052) : NULL; break; \
00610     case 053: addr = __builtin_frame_address(053) ? __builtin_return_address(053) : NULL; break; \
00611     case 054: addr = __builtin_frame_address(054) ? __builtin_return_address(054) : NULL; break; \
00612     case 055: addr = __builtin_frame_address(055) ? __builtin_return_address(055) : NULL; break; \
00613     case 056: addr = __builtin_frame_address(056) ? __builtin_return_address(056) : NULL; break; \
00614     case 057: addr = __builtin_frame_address(057) ? __builtin_return_address(057) : NULL; break; \
00615     case 060: addr = __builtin_frame_address(060) ? __builtin_return_address(060) : NULL; break; \
00616     case 061: addr = __builtin_frame_address(061) ? __builtin_return_address(061) : NULL; break; \
00617     case 062: addr = __builtin_frame_address(062) ? __builtin_return_address(062) : NULL; break; \
00618     case 063: addr = __builtin_frame_address(063) ? __builtin_return_address(063) : NULL; break; \
00619     case 064: addr = __builtin_frame_address(064) ? __builtin_return_address(064) : NULL; break; \
00620     case 065: addr = __builtin_frame_address(065) ? __builtin_return_address(065) : NULL; break; \
00621     case 066: addr = __builtin_frame_address(066) ? __builtin_return_address(066) : NULL; break; \
00622     case 067: addr = __builtin_frame_address(067) ? __builtin_return_address(067) : NULL; break; \
00623     case 070: addr = __builtin_frame_address(070) ? __builtin_return_address(070) : NULL; break; \
00624     case 071: addr = __builtin_frame_address(071) ? __builtin_return_address(071) : NULL; break; \
00625     case 072: addr = __builtin_frame_address(072) ? __builtin_return_address(072) : NULL; break; \
00626     case 073: addr = __builtin_frame_address(073) ? __builtin_return_address(073) : NULL; break; \
00627     case 074: addr = __builtin_frame_address(074) ? __builtin_return_address(074) : NULL; break; \
00628     case 075: addr = __builtin_frame_address(075) ? __builtin_return_address(075) : NULL; break; \
00629     case 076: addr = __builtin_frame_address(076) ? __builtin_return_address(076) : NULL; break; \
00630     case 077: addr = __builtin_frame_address(077) ? __builtin_return_address(077) : NULL; break; \
00631     default: addr = NULL; break; \
00632   } while (0)
00633 
00634 int print_stack( void )
00635 {
00636   Dl_info info;
00637   int level;
00638   fprintf( stderr, "Call list:\n" );
00639   for ( level = 0; level < LEVELMAX; ++level )
00640   {
00641     void *addr;
00642     get_return_address( addr, level );
00643     if ( ! addr )
00644       break;
00645     dladdr( addr, &info );
00646     fprintf( stderr, "%s(%s+%p)[%p]\n", info.dli_fname, info.dli_sname, (void *)((char *)addr - (char *)info.dli_saddr), addr );
00647   }
00648   return 0;
00649 }
00650 
00651 #endif
00652 
00653 #else /* Not using GLIBC or DARWIN ... don't do anything. */
00654 static int print_stack( void ) { return 0; }
00655 #endif
00656 
00657 #else /* Not using GCC ... don't do anything. */
00658 static int print_stack( void ) { return 0; }
00659 #endif
00660 

Generated on Fri Sep 5 03:07:45 2008 for LAL by  doxygen 1.5.2