1 #define _DEBUGTRACE_MAIN_
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include "mcw_malloc.h"
5 #ifndef MRILIB_MINI
6 #include "AFNI_version.h"
7 #endif
8 #include "debugtrace.h"  /* contains 1 function */
9 #include <ctype.h>
10 #include <stdarg.h>
11 #include <string.h>
12 
13 /*--------------------------------------------------------------------------*/
14 
15 static int colorize_prefix = 0 ;  /* use ANSI codes to change prefix colors? */
16 
17 static FILE *messfp = NULL ;
18 static char *messfn = NULL ;
19 
SET_message_file(char * fname)20 void SET_message_file( char *fname )
21 {
22    if( messfp != NULL ){ fclose(messfp); messfp = NULL; }
23    if( messfn != NULL ){ free  (messfn); messfn = NULL; }
24 
25    { char *eee = getenv("AFNI_USE_ERROR_FILE") ;  /* 22 Sep 2015 */
26      if( eee != NULL && (*eee == 'N' || *eee == 'n') ) return ;
27    }
28 
29    if( fname != NULL && *fname != '\0' ) messfn = strdup(fname) ;
30    return ;
31 }
32 
fputs_messfp(char * msg)33 static void fputs_messfp( char *msg )
34 {
35    if( messfn != NULL && messfp == NULL ) messfp = fopen(messfn,"w") ;
36    if( messfp != NULL ){ fputs(msg,messfp); fflush(messfp); }
37    return ;
38 }
39 
40 
41 /*---------------------------------------------------------------------------*/
42 /* Originally written for THD_dataset_info(), now used in other places.
43    * Used to write results into an ever-lengthening string.
44    * On the first call, 'sss' should be NULL.  It will be malloc()-ed and
45      contain the print-formatted results.
46    * On a subsequent call, 'sss' is the return value from the previous call.
47    * When finally done with it, you can free() the result.
48    * Moved here from thd_info.c on 01 May 2015 by RWCox.
49 *//*-------------------------------------------------------------------------*/
50 
51 #undef  ZMAX
52 #undef  SZMAX
53 #define ZMAX  49999        /* increased for Ziad (who else is so crazy?) */
54 #define SZMAX "%.49999s"   /* same as ZMAX */
55 
THD_zzprintf(char * sss,char * fmt,...)56 char * THD_zzprintf( char *sss , char *fmt , ... )
57 {
58    static char *sbuf = NULL ;  /* workspace */
59    char *zz ;
60    int   nzz , nsbuf ;
61    va_list vararg_ptr ;
62 
63 ENTRY("THD_zzprintf") ;
64 
65    va_start( vararg_ptr , fmt ) ;
66 
67    /* first time in ==> create workspace */
68 
69    if( sbuf == NULL ) sbuf = malloc(sizeof(char)*(ZMAX+90)) ;
70 
71    /* write current stuff into workspace */
72 
73    sbuf[0] = '\0' ;
74    vsnprintf( sbuf , sizeof(char)*(ZMAX+89) , fmt , vararg_ptr ) ;
75    nsbuf = strlen(sbuf) ;
76    if( nsbuf == 0 ) RETURN(sss) ;  /* nothing happened */
77    if( nsbuf >= ZMAX ){            /* too much happened */
78      WARNING_message("THD_zzprintf() long string truncation = the ZSS syndrome") ;
79      strcpy(sbuf+ZMAX-4,"...") ;
80      nsbuf = strlen(sbuf) ;
81    }
82 
83    /* make new space, copy input string sss, append new stuff, return result */
84 
85    if( sss == NULL || *sss == '\0' ){  /* no input string ==> copy new stuff */
86      zz = (char *) malloc( sizeof(char)*(nsbuf+8) ) ;
87      strcpy(zz,sbuf) ;
88    } else {             /* the full Monty: copy old then new */
89      nzz = strlen(sss) + nsbuf + 8 ;
90      zz  = (char *) malloc( sizeof(char) * nzz ) ;
91      strcpy(zz,sss) ; strcat(zz,sbuf) ;
92      free(sss) ;       /* don't need input copy any more */
93    }
94    RETURN(zz) ;
95 }
96 
97 /*--------------------------------------------------------------------------*/
98 /* Used to write messages into a buffer string rather than stderr */
99 
100 static int   mess_use_outbuf = 0 ;     /* 01 May 2015 */
101 static char *mess_outbuf     = NULL ;
102 
GET_message_outbuf(void)103 char * GET_message_outbuf(void){ return mess_outbuf ; }
104 
SET_message_outbuf(int use_outbuf)105 void SET_message_outbuf( int use_outbuf )
106 {
107    if( use_outbuf == 0 ){  /* turn message buffer string off */
108      mess_use_outbuf = 0 ;
109      if( mess_outbuf != NULL ) free(mess_outbuf) ;
110      mess_outbuf = NULL ;
111    } else {                /* turn it on */
112      mess_use_outbuf = 1 ;
113    }
114 }
115 
116 /*---------------------------------------------------------------------------*/
117 /* Write the message to stderr or the message buffer string.
118    If ump != 0, also write it to the message file pointer, if it is open.
119 *//*-------------------------------------------------------------------------*/
120 
output_message(int ump,char * prefix,char * fmt,va_list vararg_ptr)121 static void output_message( int ump, char *prefix, char *fmt, va_list vararg_ptr )
122 {
123    char *ifmt=NULL,*imsg=NULL , *cfmt=NULL,*cmsg=NULL , *epr=NULL ; int ll ;
124 #ifdef va_copy
125    va_list vararg_cpy ;
126    va_copy(vararg_cpy,vararg_ptr) ;        /* for re-use with cfmt and cmsg */
127 #else
128    colorize_prefix = 0 ;     /* can't do this without va_copy (C99 feature) */
129 #endif
130 
131    if( fmt == NULL || *fmt == '\0' ) return ;  /* makes no sense */
132 
133    if( colorize_prefix ){
134      epr = getenv("AFNI_MESSAGE_COLORIZE") ;
135      if( epr != NULL && toupper(*epr) == 'N' ) colorize_prefix = 0 ;
136    }
137 
138    if( prefix == NULL || *prefix == '\0' ){
139      ifmt = fmt ;
140    } else {
141      ifmt = malloc( strlen(prefix)+strlen(fmt)+4 ) ;
142      strcpy(ifmt,prefix) ;
143      strcat(ifmt,fmt) ;
144      if( colorize_prefix && !mess_use_outbuf ){         /* 22 Feb 2016 */
145        cfmt = malloc( strlen(prefix)+strlen(fmt)+64 ) ;
146 #if 0
147        strcpy(cfmt,"\033[34;1m\033[43;1m") ;  /* blue text on yellow bkgd */
148 #else
149        strcpy(cfmt,"\033[7m") ;               /* inverse colors */
150 #endif
151        strcat(cfmt,prefix) ;
152        if( prefix[strlen(prefix)-1] == ' ' )
153          cfmt[strlen(cfmt)-1] = '\0' ;
154        strcat(cfmt,"\033[0m ") ;              /* special formatting off */
155        strcat(cfmt,fmt) ;
156      }
157    }
158 
159    if( mess_use_outbuf || cfmt == NULL || ump ){
160      ll = strlen(ifmt) ; if( ll < 1024 ) ll = 1024 ;
161      epr = getenv("AFNI_MESSAGE_PREFIX") ;
162      if( epr != NULL ) ll += strlen(epr)+1 ;
163      imsg = malloc(sizeof(char)*16*ll+1) ; imsg[0] = '\0' ;
164      if( epr != NULL ){ strcpy(imsg,epr); strcat(imsg,"::"); }
165      vsprintf(imsg+strlen(imsg),ifmt,vararg_ptr) ; ll = strlen(imsg) ;
166      if( imsg[ll-1] != '\n' ){ imsg[ll] = '\n' ; imsg[ll+1] = '\0' ; }
167    }
168 
169 #ifdef va_copy
170    if( cfmt != NULL ){
171      ll = strlen(cfmt) ; if( ll < 1024 ) ll = 1024 ;
172      if( epr != NULL ) ll += strlen(epr)+1 ;
173      cmsg = malloc(sizeof(char)*16*ll+1) ; cmsg[0] = '\0' ;
174      if( epr != NULL ){ strcpy(cmsg,epr); strcat(cmsg,"::"); }
175      vsprintf(cmsg+strlen(cmsg),cfmt,vararg_cpy) ; ll = strlen(cmsg) ;
176      if( cmsg[ll-1] != '\n' ){ cmsg[ll] = '\n' ; cmsg[ll+1] = '\0' ; }
177    }
178 #endif
179 
180    if( imsg == NULL && cmsg == NULL ){ /* should never happen */
181      if( ifmt != NULL ) free(ifmt) ;
182      if( cfmt != NULL ) free(cfmt) ;
183      colorize_prefix = 0 ; return ;
184    }
185 
186    if( !mess_use_outbuf ){
187      if( cmsg != NULL ) fputs(cmsg,stderr) ;
188      else               fputs(imsg,stderr) ;
189      fflush(stderr) ; /* nugatory */
190    } else {
191      mess_outbuf = THD_zzprintf(mess_outbuf,"%s",imsg) ;  /* 01 May 2015 */
192    }
193    if( ump ) fputs_messfp(imsg) ;  /* 12 Mar 2007 */
194 
195    if( imsg != NULL ) free(imsg) ;  /* 03 Mar 2006: forgot the free! */
196    if( ifmt != fmt  ) free(ifmt) ;
197    if( cfmt != NULL ) free(cfmt) ;
198    if( cmsg != NULL ) free(cmsg) ;
199    colorize_prefix = 0 ; return ;
200 }
201 
202 /*--------------------------------------------------------------------------*/
203 
INFO_message(char * fmt,...)204 void INFO_message( char *fmt , ... )
205 {
206    va_list vararg_ptr ;
207    va_start( vararg_ptr , fmt ) ;
208    output_message( 0 , "++ " , fmt , vararg_ptr ) ;
209    va_end( vararg_ptr ) ;
210    return ;
211 }
212 
213 /*--------------------------------------------------------------------------*/
214 
ININFO_message(char * fmt,...)215 void ININFO_message( char *fmt , ... )
216 {
217    va_list vararg_ptr ;
218    va_start( vararg_ptr , fmt ) ;
219    output_message( 0 , " + " , fmt , vararg_ptr ) ;
220    va_end( vararg_ptr ) ;
221    return ;
222 }
223 
224 /*--------------------------------------------------------------------------*/
225 
WARNING_message(char * fmt,...)226 void WARNING_message( char *fmt , ... )
227 {
228    va_list vararg_ptr ;
229    va_start( vararg_ptr , fmt ) ;
230    colorize_prefix = 1 ;
231    output_message( 1 , "*+ WARNING: " , fmt , vararg_ptr ) ;
232    va_end( vararg_ptr ) ;
233    return ;
234 }
235 
236 /*--------------------------------------------------------------------------*/
237 
ERROR_message(char * fmt,...)238 void ERROR_message( char *fmt , ... )
239 {
240    va_list vararg_ptr ;
241    va_start( vararg_ptr , fmt ) ;
242    colorize_prefix = 1 ;
243    output_message( 1 , "** ERROR: " , fmt , vararg_ptr ) ;
244    va_end( vararg_ptr ) ;
245    return ;
246 }
247 
248 /*--------------------------------------------------------------------------*/
249 
ERROR_exit(char * fmt,...)250 void ERROR_exit( char *fmt , ... )
251 {
252    va_list vararg_ptr ;
253    va_start( vararg_ptr , fmt ) ;
254    colorize_prefix = 1 ;
255    output_message( 1 , "** FATAL ERROR: " , fmt , vararg_ptr ) ;
256    va_end( vararg_ptr ) ;
257    fprintf(stderr,"** Program compile date = %s\n",__DATE__) ;
258    exit(1) ;
259 }
260 
261 /*--------------------------------------------------------------------------*/
262 
263 #if 0
264 #ifdef USE_TRACING
265 void STATUS_message( char *fmt , ... )
266 {
267    char *msg ; int ll ;
268    va_list vararg_ptr ;
269    va_start( vararg_ptr , fmt ) ;
270    ll = strlen(fmt) ; if( ll < 128 ) ll = 128 ;
271    msg = malloc(sizeof(char)*16*ll+666) ; msg[0] = '\0' ;
272    sprintf(msg,"%*.*s%s -- ",DBG_num,DBG_num," ",DBROUT) ;
273    ll = strlen(msg) ;
274    vsprintf(msg+ll,fmt,vararg_ptr) ; ll = strlen(msg) ;
275    if( msg[ll-1] != '\n' ){ msg[ll] = '\n'; msg[ll+1] = '\0'; }
276    if( DBG_fp==NULL ) DBG_fp=stdout;
277    fputs(msg,DBG_fp) ;
278    strncpy(last_status,msg,1023); last_status[1023]='\0';
279    free(msg) ; va_end( vararg_ptr ) ; return ;
280 }
281 #endif
282 #endif
283 
284 /*--------------------------------------------------------------------------*/
285 /* Clock time logging [03 Nov 2016] */
286 
287 static char *pname=NULL ;
288 
set_program_name(char * ch)289 void set_program_name(char *ch)
290 {
291    if( ch != NULL ) pname = strdup(ch) ;
292    return ;
293 }
294 
295 #include <time.h>
296 extern char * nice_time_string(int) ;
297 extern int NI_clock_time(void) ;
298 extern int THD_is_directory( char * ) ;
299 
clock_time_atexit(void)300 void clock_time_atexit(void)
301 {
302 #ifndef MRILIB_MINI
303    char *eee=getenv("HOME") ;
304    int ct=NI_clock_time() ;
305    time_t tnow=time(NULL) ;
306    char *fname ; char *cht=ctime(&tnow) ;
307    FILE *fp ;
308 
309    if( ct == 0 || pname == NULL || !THD_is_directory(eee) ) return ;
310 
311    fname = (char *)malloc(sizeof(char)*(strlen(eee)+32)) ;
312    if( fname == NULL ) return ;
313    strcpy(fname,eee) ; strcat(fname,"/.afni.clocktime.log") ;
314    fp = fopen(fname,"a") ; free(fname) ; if( fp == NULL ) return ;
315    fprintf(fp,"[%.24s] %s =%s\n",ctime(&tnow) , pname , nice_time_string(ct) ) ;
316    fclose(fp) ;
317 #endif
318    return ;
319 }
320