From ba4821ed7ee6aef53ec48d3739c77edad8bd7858 Mon Sep 17 00:00:00 2001 From: goodale Date: Mon, 3 Oct 2005 13:14:28 +0000 Subject: Patch from Jian Tao to add some callback functionality to the warning system. This allows thorns to register functions which will be called when CCTK_Warn or CCTK_Info are called, with the contents of the warning/info message, thus allowing thorns to do things like logging warnings to file or displaying on webpages. git-svn-id: http://svn.cactuscode.org/flesh/trunk@4157 17b73243-c579-4c4c-a9d2-2d5706c11dac --- src/include/cctk_WarnLevel.h | 26 +++- src/main/WarnLevel.c | 319 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 342 insertions(+), 3 deletions(-) diff --git a/src/include/cctk_WarnLevel.h b/src/include/cctk_WarnLevel.h index d867eae9..e826bfdf 100644 --- a/src/include/cctk_WarnLevel.h +++ b/src/include/cctk_WarnLevel.h @@ -47,11 +47,35 @@ __attribute__ ((format (printf, 2, 3))) #endif ; +/* prototypes for warn/info callback routines */ + +typedef void (*cctk_warnfunc)(int level, + int line, + const char *file, + const char *thorn, + const char *message, + void *data); + +typedef void (*cctk_infofunc)(const char *thorn, + const char *message, + void *data); + +/* prototypes for warn/info registration routines */ +int CCTK_WarnCallbackRegister(int minlevel, + int maxlevel, + void *data, + cctk_warnfunc callback); + + +int CCTK_InfoCallbackRegister(void *data, + cctk_infofunc callback); + + #ifdef __cplusplus } #endif -#endif /* CCODE */ +#endif /* CCODE */ /* suggested values for warning levels (courtesy of Steve, PR#1742) */ #define CCTK_WARN_ABORT 0 /* abort the Cactus run */ diff --git a/src/main/WarnLevel.c b/src/main/WarnLevel.c index c3db295e..3d5872f9 100644 --- a/src/main/WarnLevel.c +++ b/src/main/WarnLevel.c @@ -66,11 +66,45 @@ void CCTK_FCALL CCTK_FNAME (CCTK_Warn) THREE_FORTSTRING_ARG); void CCTK_FCALL CCTK_FNAME (CCTK_ParamWarn) (TWO_FORTSTRING_ARG); -int CCTK_FCALL CCTK_FNAME (CCTK_MessageFormat) +int CCTK_FCALL CCTK_FNAME (CCTK_MessageFormat) (ONE_FORTSTRING_ARG); void CCTK_FCALL CCTK_FNAME (CCTKi_NotYetImplemented) (ONE_FORTSTRING_ARG); +/******************************************************************** + ******************** Internal Typedefs ************************ + ********************************************************************/ +/* structure holding a callback function pointer together with other + * information to warn/info*/ + +typedef struct warncallback +{ + struct warncallback *next; + cctk_warnfunc function; + void *data; + int minlevel; + int maxlevel; +} t_warncallback; + +typedef struct infocallback +{ + struct infocallback *next; + cctk_infofunc function; + void *data; +} t_infocallback; + + +/******************************************************************** + ******************** Internal Functions ************************ + ********************************************************************/ + +static void CCTKi_WarnCallbacksCall(int level, + int line, + const char *file, + const char *thorn, + const char *message); + +static void CCTKi_InfoCallbacksCall(const char *thorn, const char *message); /******************************************************************** ********************* Static Data ***************************** @@ -101,6 +135,10 @@ static int error_level = 0; static int n_formats = 0; static pKeyedData *formatlist = NULL; +/* Store registered warn and info methods */ +static t_warncallback *warncallbacks = NULL; +static t_infocallback *infocallbacks = NULL; + /*@@ @routine CCTK_Info @@ -179,12 +217,45 @@ void CCTK_FCALL CCTK_FNAME (CCTK_Info) int CCTK_VInfo (const char *thorn, const char *format, ...) { va_list ap; - + int retval = -1; static int info_format_decoded = 0; /* are the following two flags valid? */ /* Boolean flags decoded from cactus::info_format */ static int info_format_numeric = 0; /* print a numeric timestamp? */ static int info_format_human_readable = 0; /* print a human-readable timestamp? */ +/* necessary for wrapping up the final message */ + int msg_size; + char *message = NULL; + +/* Start generating message only if the infocallback list is not NULL */ + if(infocallbacks) + { + va_start(ap,format); + +/* one way to get the final string size */ + msg_size = Util_vsnprintf(NULL, 0, format, ap); + +/* Empty string is ok */ + if(msg_size >= 0) + { + message = (char *)malloc(msg_size+1); + } + +/* Try to print in the allocated space. */ + if(message) + { + va_start(ap,format); + Util_vsnprintf(message,msg_size+1,format,ap); + va_end(ap); + } + +/* call the callback function */ + CCTKi_InfoCallbacksCall(thorn,message); + +/* free the memory allocated for temp messsage */ + free (message); + } + /* * if we haven't already decoded cactus::info_format into the * Boolean flags, do so @@ -394,6 +465,39 @@ int CCTK_VWarn (int level, int param_type; int myproc; va_list ap, aq; + int retval = -1; + +/* Necessary for wrapping up the final message */ + + int msg_size; + char *message = NULL; + +/* Start generating message only if the warbcallback list is not NULL */ + if(warncallbacks) + { + va_start(ap,format); + msg_size = Util_vsnprintf(NULL, 0, format, ap); + +/* Empty string is ok */ + if(msg_size >= 0) + { + message = (char *)malloc(msg_size+1); + } + +/* Try to print in the allocated space. */ + if(message) + { + va_start(ap,format); + Util_vsnprintf(message,msg_size+1,format,ap); + va_end(ap); + } + +/* call the callback function */ + CCTKi_WarnCallbacksCall(level,line,file,thorn,message); + +/* free the memory allocated for temp messsage */ + free (message); + } if (level <= warning_level || level <= logging_level) { @@ -659,6 +763,121 @@ int CCTK_VParamWarn (const char *thorn, return (0); } +/*@@ + @routine CCTK_WarnCallbackRegister + @date 05/17/2005 + @author Jian Tao + @desc + Register warn callback function + @enddesc + @endvar + @var minlevel + @vdesc minimum warning level + @vtype int + @vio in + @endvar + @var maxlevel + @vdesc maximum warning level + @vtype int + @vio in + @endvar + @var data + @vdesc + @vtype int* + @vio in + @endvar + @var function + @vdesc Callback function (see cctk_WarnLevel.h) + @vtype cctk_warnfunc + @vio in + @endvar +@@*/ + +int CCTK_WarnCallbackRegister(int minlevel, + int maxlevel, + void *data, + cctk_warnfunc callback) + +{ + int retval; + t_warncallback *newcallback; + + newcallback = (t_warncallback *)malloc(sizeof(t_warncallback)); + +/* Create a one way chain for all registered callbacks */ + if(newcallback) + { + newcallback->next = warncallbacks; + warncallbacks = newcallback; + newcallback->function = callback; + newcallback->data = data; + newcallback->minlevel = minlevel; + newcallback->maxlevel = maxlevel; + retval = 0; + } + else + { + retval = -1; + } + return retval; +} + + +/*@@ + @routine CCTK_InfoCallbackRegister + @date 05/17/2005 + @author Jian Tao + @desc + Register info callback function + @enddesc + @endvar + @var minlevel + @vdesc minimum warning level + @vtype int + @vio in + @endvar + @var maxlevel + @vdesc maximum warning level + @vtype int + @vio in + @endvar + @var data + @vdesc + @vtype int* + @vio in + @endvar + @var function + @vdesc Callback function (see cctk_WarnLevel.h) + @vtype cctk_infofunc + @vio in + @endvar +@@*/ + +int CCTK_InfoCallbackRegister(void *data, cctk_infofunc callback) + +{ + int retval; + t_infocallback *newcallback; + + newcallback = (t_infocallback *)malloc(sizeof(t_infocallback)); + +/* Create a one way chain for all registered callbacks */ + if(newcallback) + { + newcallback->next = infocallbacks; + infocallbacks = newcallback; + newcallback->function = callback; + newcallback->data = data; + retval = 0; + } + + else + { + retval = -1; + } + return retval; +} + /*@@ @routine CCTK_MessageFormat @@ -1043,4 +1262,100 @@ void CCTK_FCALL CCTK_FNAME (CCTK_VInfo) } } + #endif + +/*@@ + @routine CCTKi_WarnCallbacksCall + @date 05/17/2005 + @author Jian Tao + @desc + Call callback functions + @enddesc + @var level + @vdesc Warning level + @vtype int + @vio in + @endvar + @var line + @vdesc Line number of warning in originating file + @vtype int + @vio in + @endvar + @var file + @vdesc Name of originating file + @vtype const char * + @vio in + @endvar + @var thorn + @vdesc Name of originating thorn + @vtype const char * + @vio in + @endvar + @var message + @vdesc warning message to output to stderr + @vtype const char * + @vio in + @endvar +@@*/ + +static void CCTKi_WarnCallbacksCall(int level, + int line, + const char *file, + const char *thorn, + const char *message) +{ + t_warncallback *current; + +/* + * Go through all the registered call back functions + * static variable warncallbacks has already been checked to be not empty + */ + + for(current=warncallbacks; current; current=current->next) + { + +/* Check valid level */ + if(level >= current->minlevel && level <= current->maxlevel) + { + current->function(level,line,file,thorn,message,current->data); + } + + } + return; +} + +/*@@ + @routine CCTKi_InfoCallbacksCall + @date 05/17/2005 + @author Jian Tao + @desc + Call callback functions + @enddesc + @var thorn + @vdesc Name of originating thorn + @vtype const char * + @vio in + @endvar + @var message + @vdesc warning message to output to stderr + @vtype const char * + @vio in + @endvar +@@*/ + +static void CCTKi_InfoCallbacksCall(const char *thorn, const char *message) +{ + t_infocallback *current; + +/* + * Go through all the registered call back functions + * static variable infocallbacks has already been checked to be not empty + */ + + for(current=infocallbacks; current; current=current->next) + { + current->function(thorn,message,current->data); + } + return; +} -- cgit v1.2.3