/*****************************************************************************
Major portions of this software are copyrighted by the Medical College
of Wisconsin, 1994-2000, and are released under the Gnu General Public
License, Version 2. See the file README.Copyright for details.
******************************************************************************/
#ifndef _MCW_DEBUGTRACE_
#define _MCW_DEBUGTRACE_
/** inputs:
USE_TRACING ==> if set, include tracing information **/
/*** Modified 23 Aug 1998 to eliminate PRINT_TRACING.
Now, if DBG_trace > 1, will print STATUS messages. ***/
/*** Modified 06 Mar 1999 to eliminate GNU malloc stuff,
and replace it with mcw_malloc stuff. ***/
/*** Modified 26 Jan 2001 to separate it more fully from
AFNI itself and incorporate it into the mrilib. ***/
/*** 20 Feb 2001: added TRACEBACK and EXIT macros ***/
/*-------------------------------------------------------------------
29 Jan 2001: a hack for debugging files selectively
---------------------------------------------------------------------*/
#ifndef TWO_TWO
/** combine two interpreted tokens into one using TWO_TWO **/
# define TWO_ONE(x,y) x ## y
# define TWO_TWO(x,y) TWO_ONE(x,y)
#endif
/*********************************************************************/
#ifdef USE_TRACING
#define DEBUG_MAX_DEPTH 1024 /* way too big, but who cares? */
#define DBG_label DBG_labels[DBG_trace]
/*---------------------------------------------------------------*/
#ifdef DONT_USE_MCW_MALLOC
# define MCHECK /* nada */
# define MPROBE /* nada */
#else
# define MCHECK \
do{ char *mc = MCW_MALLOC_status ; \
if( DBG_fp==NULL ) DBG_fp=stdout; \
if( mc != NULL ){ \
fprintf(DBG_fp,"** Memory usage: %s\n",mc); \
fflush(DBG_fp) ; \
} \
} while(0)
# define MPROBE do{ if( !DBG_trace ) (void)MCW_MALLOC_status ; } while(0)
#endif
#define TRACEBACK DBG_traceback() /* 20 Feb 2001 */
/*----------------------------------------------------------------
Define things to be used in debugtrace.c
------------------------------------------------------------------*/
#include <signal.h>
#include <unistd.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _DEBUGTRACE_MAIN_
char * DBG_rout[DEBUG_MAX_DEPTH] = { "Bottom of Debug Stack" } ;
int DBG_num = 1 ;
int DBG_trace = 0 ; /* turn off at start (cf. mainENTRY) */
FILE *DBG_fp = NULL ; /* 01 Sep 2006 */
char * DBG_labels[3] = { "Trace=OFF " , "Trace=LOW " , "Trace=HIGH" } ;
char last_status[1024] = "\0" ; /* 22 Apr 2002 */
void DBG_traceback(void)
{ int tt ;
MCHECK ;
if( last_status[0] != '\0' )
fprintf(stderr,"Last STATUS: %s\n",last_status) ;
for( tt=DBG_num-1; tt >= 1 ; tt-- )
fprintf(stderr,"%*.*s%s\n",tt+1,tt+1," ",DBG_rout[tt]) ;
}
void DBG_sigfunc(int sig) /** signal handler for fatal errors **/
{
char * sname ; int ii ;
static volatile int fff=0 ;
if( fff ) _exit(1); else fff=1 ;
switch(sig){
default: sname = "unknown" ; break ;
case SIGPIPE: sname = "SIGPIPE" ; break ;
case SIGSEGV: sname = "SIGSEGV" ; break ;
case SIGBUS: sname = "SIGBUS" ; break ;
case SIGINT: sname = "SIGINT" ; break ;
case SIGTERM: sname = "SIGTERM" ; break ;
}
fprintf(stderr,"\nFatal Signal %d (%s) received\n",sig,sname) ;
if( last_status[0] != '\0' )
fprintf(stderr,"Last STATUS: %s\n",last_status) ;
if( DBG_num >= 0 ){
for( ii=DBG_num-1; ii >= 0 ; ii-- )
fprintf(stderr,"%*.*s%s\n",ii+1,ii+1," ",DBG_rout[ii]) ;
} else {
fprintf(stderr,"[No debug tracing stack: DBG_num=%d]\n",DBG_num) ;
}
#ifdef AFNI_VERSION_LABEL
fprintf(stderr,"** AFNI version = " AFNI_VERSION_LABEL
" Compile date = " __DATE__ "\n" );
#endif
fprintf(stderr,"** Program Abort **\n") ; fflush(stderr) ;
MPROBE ; exit(1) ;
}
/*---------------------------------------------------------------
Call out the variables defined in debugtrace.c
-----------------------------------------------------------------*/
#else /* not _DEBUGTRACE_MAIN_ */
extern char * DBG_rout[DEBUG_MAX_DEPTH] ;
extern int DBG_num ;
extern int DBG_trace ;
extern FILE *DBG_fp ;
extern char * DBG_labels[3] ;
extern void DBG_sigfunc(int) ;
extern void DBG_traceback(void) ;
extern char last_status[1024] ;
#endif /* _DEBUGTRACE_MAIN_ */
#define DBG_SIGNALS ( signal(SIGPIPE,DBG_sigfunc) , \
signal(SIGSEGV,DBG_sigfunc) , \
signal(SIGINT ,DBG_sigfunc) , \
signal(SIGBUS ,DBG_sigfunc) , \
signal(SIGTERM,DBG_sigfunc) )
/*---------------------------------------------------------------*/
/* macros for entering and exiting a function */
#define DBG_LEADER_IN "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
#define DBG_LEADER_OUT "-----------------------------------------------------------"
#define ENTRY(rout) do{ static char * rrr = (rout) ; DBG_rout[DBG_num++] = rrr ; \
if( DBG_trace ){ \
if( DBG_fp == NULL ) DBG_fp = stdout ; \
fprintf(DBG_fp, \
"%*.*s%s [%d]: ENTRY (file=%s line=%d)\n", \
DBG_num,DBG_num,DBG_LEADER_IN,rrr,DBG_num, \
__FILE__ , __LINE__ ) ; \
MCHECK ; fflush(DBG_fp) ; } \
last_status[0] = '\0' ; \
} while(0)
#define DBROUT DBG_rout[DBG_num-1]
#define DBEXIT do{ if( DBG_trace ){ \
if( DBG_fp == NULL ) DBG_fp = stdout ; \
fprintf(DBG_fp, \
"%*.*s%s [%d]: EXIT (file=%s line=%d)\n", \
DBG_num,DBG_num,DBG_LEADER_OUT,DBROUT,DBG_num, \
__FILE__ , __LINE__ ); \
MCHECK ; fflush(DBG_fp) ; } \
DBG_num = (DBG_num>1) ? DBG_num-1 : 1 ; \
last_status[0] = '\0' ; \
} while(0)
/*! This macro is only to be used inside main(). */
#define mainENTRY(rout) \
do{ char *e=getenv("AFNI_TRACE"); \
if( e != NULL ) DBG_trace = (*e=='y') ? 1 : (*e=='Y') ? 2 : 0 ; \
e = getenv("AFNI_TRACE_FILE") ; \
if( e != NULL ) DBG_fp=fopen(e,"w") ; \
if( DBG_fp==NULL ) DBG_fp=stdout; \
DBG_SIGNALS ; ENTRY(rout) ; } while(0)
#define PRINT_TRACING (DBG_trace > 1)
#define STATUS(str) \
do{ if(PRINT_TRACING){ \
MCHECK ; if( DBG_fp==NULL ) DBG_fp=stdout; \
fprintf(DBG_fp,"%*.*s%s -- %s\n",DBG_num,DBG_num," ",DBROUT,(str)); \
fflush(DBG_fp) ; } \
strncpy(last_status,str,1023); last_status[1023]='\0'; \
} while(0)
/*********************************************************************/
#else /* don't USE_TRACING */
# define ENTRY(rout) /* nada */
# define DBEXIT /* nada */
# define DBROUT /* nada */
# define STATUS(str) /* nada */
# define DBG_SIGNALS /* nada */
# define MCHECK /* nada */
# define MPROBE /* nada */
# define TRACEBACK /* nada */
# define PRINT_TRACING 0
# define DBG_trace 0 /* 09 Dec 1999 */
# ifdef _DEBUGTRACE_MAIN_
void DBG_sigfunc(int sig){} /* does nada */
# else
extern void DBG_sigfunc(int) ;
# endif
# define mainENTRY(rout) /* nada */
#endif /* USE_TRACING */
/*********************************************************************/
/* these macros are always defined here */
#undef RETURN
#undef EXRETURN
#undef EXIT
#define RETURN(val) do{ DBEXIT ; return (val) ; } while(0)
#define EXRETURN do{ DBEXIT ; return ; } while(0)
#define EXIT(n) do{ TRACEBACK ; exit(n) ; } while(0)
/*---------------------------------------------------------------*/
#ifndef MCHECK
# define MCHECK /* nada */
# define MPROBE /* nada */
#endif
#ifdef __cplusplus
}
#endif
/*---------------------------------------------------------------*/
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif
extern void INFO_message ( char *fmt , ... ) ; /* 13 Jul 2005 */
extern void ININFO_message ( char *fmt , ... ) ;
extern void WARNING_message( char *fmt , ... ) ;
extern void ERROR_message ( char *fmt , ... ) ;
extern void ERROR_exit ( char *fmt , ... ) ;
extern void SET_message_file( char *fname ) ; /* 09 Mar 2007 */
#define FATAL_ERROR_message ERROR_exit
#ifdef __cplusplus
}
#endif
#endif /* _MCW_DEBUGTRACE_ */
syntax highlighted by Code2HTML, v. 0.9.1