1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This1 file is part of the program and library             */
4    	/*         SCIP --- Solving Constraint Integer Programs                      */
5    	/*                                                                           */
6    	/*    Copyright (C) 2002-2021 Konrad-Zuse-Zentrum                            */
7    	/*                            fuer Informationstechnik Berlin                */
8    	/*                                                                           */
9    	/*  SCIP is distributed under the terms of the ZIB Academic License.         */
10   	/*                                                                           */
11   	/*  You should have received a copy of the ZIB Academic License              */
12   	/*  along with SCIP; see the file COPYING. If not visit scipopt.org.         */
13   	/*                                                                           */
14   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15   	
16   	/**@file   message.c
17   	 * @ingroup OTHER_CFILES
18   	 * @brief  message output methods
19   	 * @author Tobias Achterberg
20   	 * @author Marc Pfetsch
21   	 * @author Michael Winkler
22   	 */
23   	
24   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
25   	
26   	#include <stdarg.h>
27   	#include <stdio.h>
28   	#include <assert.h>
29   	
30   	#include "scip/struct_message.h"
31   	#include "scip/pub_message.h"
32   	#include "scip/def.h"
33   	#include "scip/pub_misc.h"
34   	#include "blockmemshell/memory.h"
35   	
36   	
37   	#ifndef va_copy
38   	#define va_copy(dest, src) do { BMScopyMemory(&dest, &src); } while( 0 )
39   	#endif
40   	
41   	/* do defines for windows directly her to make the lpi more independent*/
42   	#if defined(_WIN32) || defined(_WIN64)
43   	#define snprintf _snprintf
44   	#define vsnprintf _vsnprintf
45   	#endif
46   	
47   	/** handles the output of the given message */
48   	static
49   	void handleMessage(
50   	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
51   	   SCIP_DECL_MESSAGEOUTPUTFUNC(outputfunc),  /**< message handler function used for output */
52   	   FILE*                 file1,              /**< file stream to print into, or NULL for stdout */
53   	   SCIP_Bool             usefile1,           /**< Should file1 be used? */
54   	   FILE*                 file2,              /**< file stream to print into */
55   	   SCIP_Bool             usefile2,           /**< Should file2 be used? */
56   	   const char*           msg,                /**< message to print; NULL to flush the output buffer */
57   	   char*                 buffer,             /**< message buffer */
58   	   int*                  bufferlen           /**< pointer to the currently used entries in the message buffer */
59   	   )
60   	{
61   	   const char* s;
62   	
63   	   assert( messagehdlr != NULL );
64   	   assert( outputfunc != NULL );
65   	   assert( !usefile2 || file2 != NULL );
66   	   assert( buffer == NULL || bufferlen != NULL );
67   	
68   	   /* if we do not have a buffer directly output the message */
69   	   if ( buffer == NULL )
70   	   {
71   	      /* we do not have a buffer, so it makes no sense to flush it if msg == NULL */
72   	      if ( msg != NULL )
73   	      {
74   	         if ( usefile1 )
75   	            outputfunc(messagehdlr, file1, msg);
76   	         if ( usefile2 )
77   	            outputfunc(messagehdlr, file2, msg);
78   	      }
79   	      return;
80   	   }
81   	   assert(bufferlen != NULL);
82   	
83   	   /* should the buffer be flushed? */
84   	   if ( msg == NULL )
85   	   {
86   	      assert( *bufferlen < SCIP_MAXSTRLEN );
87   	      assert( buffer[*bufferlen] == '\0' );
88   	      if ( usefile1 )
89   	         outputfunc(messagehdlr, file1, buffer);
90   	      if ( usefile2 )
91   	         outputfunc(messagehdlr, file2, buffer);
92   	      *bufferlen = 0;
93   	      buffer[0] = '\0';
94   	      return;
95   	   }
96   	   assert( msg != NULL && buffer != NULL );
97   	
98   	   /* if no output is activated, to not copy message into buffer */
99   	   if ( ! usefile1 && ! usefile2 )
100  	      return;
101  	
102  	   /* determine message length and last newline (if any) */
103  	   s = msg;
104  	   while ( *s != '\0' )
105  	   {
106  	      /* if we reached a newline or the size limit, empty buffer and reset (need possibly space for newline and '\0') */
107  	      if ( *s == '\n' || *bufferlen >= SCIP_MAXSTRLEN-2 )
108  	      {
109  	         if ( *s == '\n' )
110  	            buffer[(*bufferlen)++] = *(s++);
111  	         buffer[*bufferlen] = '\0';
112  	
113  	         if ( usefile1 )
114  	            outputfunc(messagehdlr, file1, buffer);
115  	         if ( usefile2 )
116  	            outputfunc(messagehdlr, file2, buffer);
117  	         *bufferlen = 0;
118  	         buffer[0] = '\0';
119  	      }
120  	      else
121  	         buffer[(*bufferlen)++] = *(s++);
122  	   }
123  	   buffer[*bufferlen] = '\0';
124  	
125  	   return;
126  	}
127  	
128  	/** default error printing method which is used to print all occurring errors */
129  	static
130  	SCIP_DECL_ERRORPRINTING(errorPrintingDefault)
131  	{  /*lint --e{715}*/
132  	   if ( msg != NULL )
133  	   {
134  	      if ( file != NULL )
135  	         fputs(msg, file);
136  	      else
137  	         fputs(msg, stderr);
138  	   }
139  	   fflush(stderr);
140  	}
141  	
142  	/** static variable which holds the error printing method */
143  	static SCIP_DECL_ERRORPRINTING((*staticErrorPrinting)) = errorPrintingDefault;
144  	
145  	/** static variable which holds a data pointer for the error prinint callback */
146  	static void* staticErrorPrintingData = NULL;
147  	
148  	/** prints error message with the current static message handler */
149  	static
150  	void messagePrintError(
151  	   FILE*                 file,               /**< file stream to print error, or NULL for stderr */
152  	   const char*           msg                 /**< message to print; NULL to flush the output buffer */
153  	   )
154  	{
155  	   if( staticErrorPrinting != NULL )
156  	      staticErrorPrinting(staticErrorPrintingData, file, msg);
157  	}
158  	
159  	/** prints warning message with the current message handler, or buffers the message if no newline exists */
160  	static
161  	void messagePrintWarning(
162  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
163  	   const char*           msg                 /**< message to print; NULL to flush the output buffer */
164  	   )
165  	{  /*lint --e{715}*/
166  	   if ( messagehdlr != NULL && messagehdlr->messagewarning != NULL && (! messagehdlr->quiet || messagehdlr->logfile != NULL) )
167  	   {
168  	      handleMessage(messagehdlr, messagehdlr->messagewarning, stderr, ! messagehdlr->quiet, messagehdlr->logfile, (messagehdlr->logfile != NULL),
169  	         msg, messagehdlr->warningbuffer, &messagehdlr->warningbufferlen);
170  	   }
171  	}
172  	
173  	/** prints dialog message with the current message handler, or buffers the message if no newline exists */
174  	static
175  	void messagePrintDialog(
176  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
177  	   FILE*                 file,               /**< file stream to print into, or NULL for stdout */
178  	   const char*           msg                 /**< message to print; NULL to flush the output buffer */
179  	   )
180  	{  /*lint --e{715}*/
181  	   if ( messagehdlr != NULL && messagehdlr->messagedialog != NULL )
182  	   {
183  	      if ( (file == NULL || file == stdout) && ! messagehdlr->quiet )
184  	      {
185  	         handleMessage(messagehdlr, messagehdlr->messagedialog, (file == NULL) ? stdout : file, TRUE, messagehdlr->logfile, (messagehdlr->logfile != NULL),
186  	            msg, messagehdlr->dialogbuffer, &messagehdlr->dialogbufferlen);
187  	      }
188  	      else if ( msg != NULL )
189  	      {
190  	         /* file output cannot be buffered because the output file may change */
191  	         if ( *msg != '\0' )
192  	         {
193  	            handleMessage(messagehdlr, messagehdlr->messagedialog, file, !messagehdlr->quiet || (file != NULL && file != stdout), messagehdlr->logfile, (messagehdlr->logfile != NULL), msg, NULL, NULL);
194  	         }
195  	      }
196  	   }
197  	}
198  	
199  	/** prints info message with the current message handler, or buffers the message if no newline exists */
200  	static
201  	void messagePrintInfo(
202  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
203  	   FILE*                 file,               /**< file stream to print into, or NULL for stdout */
204  	   const char*           msg                 /**< message to print; NULL to flush the output buffer */
205  	   )
206  	{  /*lint --e{715}*/
207  	   if ( messagehdlr != NULL && messagehdlr->messageinfo != NULL )
208  	   {
209  	      if ( (file == NULL || file == stdout) && ! messagehdlr->quiet )
210  	      {
211  	         handleMessage(messagehdlr, messagehdlr->messageinfo, (file == NULL) ? stdout : file, TRUE, messagehdlr->logfile, (messagehdlr->logfile != NULL),
212  	            msg, messagehdlr->infobuffer, &messagehdlr->infobufferlen);
213  	      }
214  	      else if ( msg != NULL )
215  	      {
216  	         /* file output cannot be buffered because the output file may change or the message is to long */
217  	         if ( *msg != '\0' )
218  	         {
219  	            handleMessage(messagehdlr, messagehdlr->messagedialog, file, !messagehdlr->quiet || (file != NULL && file != stdout), messagehdlr->logfile, (messagehdlr->logfile != NULL), msg, NULL, NULL);
220  	         }
221  	      }
222  	   }
223  	}
224  	
225  	/** if the given file is not NULL a log file is opened */
226  	static
227  	void messagehdlrOpenLogfile(
228  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
229  	   const char*           filename            /**< name of log file, or NULL (stdout) */
230  	   )
231  	{
232  	   if( filename != NULL )
233  	   {
234  	      messagehdlr->logfile = fopen(filename, "a"); /* append to log file */
235  	
236  	      if( messagehdlr->logfile == NULL )
237  	      {
238  	         SCIPerrorMessage("cannot open log file <%s> for writing\n", filename);
239  	      }
240  	   }
241  	   else
242  	      messagehdlr->logfile = NULL;
243  	}
244  	
245  	/** frees message handler */
246  	static
247  	SCIP_RETCODE messagehdlrFree(
248  	   SCIP_MESSAGEHDLR**    messagehdlr         /**< pointer to the message handler */
249  	   )
250  	{
251  	   assert(messagehdlr != NULL);
252  	
253  	   if( *messagehdlr != NULL )
254  	   {
255  	      /* flush message buffers */
256  	      messagePrintWarning(*messagehdlr, NULL);
257  	      messagePrintDialog(*messagehdlr, NULL, NULL);
258  	      messagePrintInfo(*messagehdlr, NULL, NULL);
259  	
260  	      if( (*messagehdlr)->messagehdlrfree != NULL )
261  	      {
262  	         /* call destructor method of message handler to free the message handler data */
263  	         SCIP_CALL( (*messagehdlr)->messagehdlrfree(*messagehdlr) );
264  	      }
265  	
266  	      /* close the log file if one exists */
267  	      if( (*messagehdlr)->logfile != NULL )
268  	      {
269  	         fclose((*messagehdlr)->logfile);
270  	      }
271  	
272  	      /* free buffer arrays */
273  	      BMSfreeMemoryArrayNull(&(*messagehdlr)->warningbuffer);
274  	      BMSfreeMemoryArrayNull(&(*messagehdlr)->dialogbuffer);
275  	      BMSfreeMemoryArrayNull(&(*messagehdlr)->infobuffer);
276  	      BMSfreeMemory(messagehdlr);
277  	   }
278  	
279  	   return SCIP_OKAY;
280  	}
281  	
282  	/** Creates and captures a message handler which deals with warning, information, and dialog (interactive shell) methods.
283  	 *
284  	 *  @note The message handler does not handle error messages; see SCIPmessageSetErrorPrinting()
285  	 */
286  	SCIP_RETCODE SCIPmessagehdlrCreate(
287  	   SCIP_MESSAGEHDLR**    messagehdlr,        /**< pointer to store the message handler */
288  	   SCIP_Bool             bufferedoutput,     /**< should the output be buffered up to the next newline? */
289  	   const char*           filename,           /**< name of log file, or NULL for no log */
290  	   SCIP_Bool             quiet,              /**< should screen messages be suppressed? */
291  	   SCIP_DECL_MESSAGEWARNING((*messagewarning)),/**< warning message print method of message handler */
292  	   SCIP_DECL_MESSAGEDIALOG((*messagedialog)),/**< dialog message print method of message handler */
293  	   SCIP_DECL_MESSAGEINFO ((*messageinfo)),   /**< info message print method of message handler */
294  	   SCIP_DECL_MESSAGEHDLRFREE((*messagehdlrfree)), /**< destructor of message handler to free message handler data */
295  	   SCIP_MESSAGEHDLRDATA* messagehdlrdata     /**< message handler data */
296  	   )
297  	{
298  	   SCIP_ALLOC( BMSallocMemory(messagehdlr) );
299  	   (*messagehdlr)->messagewarning = messagewarning;
300  	   (*messagehdlr)->messagedialog = messagedialog;
301  	   (*messagehdlr)->messageinfo = messageinfo;
302  	   (*messagehdlr)->messagehdlrfree = messagehdlrfree;
303  	   (*messagehdlr)->messagehdlrdata = messagehdlrdata;
304  	   (*messagehdlr)->warningbuffer = NULL;
305  	   (*messagehdlr)->dialogbuffer = NULL;
306  	   (*messagehdlr)->infobuffer = NULL;
307  	   (*messagehdlr)->warningbufferlen = 0;
308  	   (*messagehdlr)->dialogbufferlen = 0;
309  	   (*messagehdlr)->infobufferlen = 0;
310  	   (*messagehdlr)->nuses = 1;
311  	
312  	   (*messagehdlr)->quiet = quiet;
313  	   messagehdlrOpenLogfile(*messagehdlr, filename);
314  	
315  	   /* allocate buffer for buffered output */
316  	   if( bufferedoutput )
317  	   {
318  	      SCIP_ALLOC( BMSallocMemoryArray(&(*messagehdlr)->warningbuffer, SCIP_MAXSTRLEN) ); /*lint !e506*/
319  	      SCIP_ALLOC( BMSallocMemoryArray(&(*messagehdlr)->dialogbuffer, SCIP_MAXSTRLEN) ); /*lint !e506*/
320  	      SCIP_ALLOC( BMSallocMemoryArray(&(*messagehdlr)->infobuffer, SCIP_MAXSTRLEN) ); /*lint !e506*/
321  	      (*messagehdlr)->warningbuffer[0] = '\0';
322  	      (*messagehdlr)->dialogbuffer[0] = '\0';
323  	      (*messagehdlr)->infobuffer[0] = '\0';
324  	   }
325  	
326  	   return SCIP_OKAY;
327  	}
328  	
329  	/** captures message handler */
330  	void SCIPmessagehdlrCapture(
331  	   SCIP_MESSAGEHDLR*     messagehdlr         /**< message handler, or NULL */
332  	   )
333  	{
334  	   if( messagehdlr != NULL )
335  	      ++messagehdlr->nuses;
336  	}
337  	
338  	/** releases message handler */
339  	SCIP_RETCODE SCIPmessagehdlrRelease(
340  	   SCIP_MESSAGEHDLR**    messagehdlr         /**< pointer to the message handler */
341  	   )
342  	{
343  	   assert(messagehdlr != NULL);
344  	
345  	   if( *messagehdlr == NULL )
346  	      return SCIP_OKAY;
347  	
348  	   assert((*messagehdlr)->nuses >= 1);
349  	
350  	   /* decrement usage counter */
351  	   --(*messagehdlr)->nuses;
352  	
353  	   /* the last one turns the light off */
354  	   if( (*messagehdlr)->nuses == 0 )
355  	   {
356  	      SCIP_CALL( messagehdlrFree(messagehdlr) );
357  	      assert(*messagehdlr == NULL);
358  	   }
359  	   else
360  	   {
361  	      *messagehdlr = NULL;
362  	   }
363  	
364  	   return SCIP_OKAY;
365  	}
366  	
367  	/** sets the user data of the message handler */
368  	SCIP_RETCODE SCIPmessagehdlrSetData(
369  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler; must not be NULL */
370  	   SCIP_MESSAGEHDLRDATA* messagehdlrdata     /**< new message handler data to attach to the handler */
371  	   )
372  	{
373  	   assert(messagehdlr != NULL);
374  	
375  	   if( messagehdlr == NULL ) /*lint !e774*/
376  	      return SCIP_INVALIDDATA;
377  	
378  	   messagehdlr->messagehdlrdata = messagehdlrdata;
379  	
380  	   return SCIP_OKAY;
381  	}
382  	
383  	/** sets the log file name for the message handler */
384  	void SCIPmessagehdlrSetLogfile(
385  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
386  	   const char*           filename            /**< log file name where to copy messages into, or NULL */
387  	   )
388  	{
389  	   assert(messagehdlr != NULL);
390  	
391  	   /* close the old log file if one exists */
392  	   if( messagehdlr->logfile != NULL )
393  	   {
394  	      fclose(messagehdlr->logfile);
395  	   }
396  	
397  	   /* opens the log file */
398  	   messagehdlrOpenLogfile(messagehdlr, filename);
399  	}
400  	
401  	/** sets the messages handler to be quiet */
402  	void SCIPmessagehdlrSetQuiet(
403  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
404  	   SCIP_Bool             quiet               /**< should screen messages be suppressed? */
405  	   )
406  	{
407  	   assert(messagehdlr != NULL);
408  	
409  	   /* flush message buffers in order to not loose information */
410  	   messagePrintWarning(messagehdlr, NULL);
411  	   messagePrintDialog(messagehdlr, NULL, NULL);
412  	   messagePrintInfo(messagehdlr, NULL, NULL);
413  	
414  	   messagehdlr->quiet = quiet;
415  	}
416  	
417  	/** prints a warning message, acting like the printf() command */
418  	void SCIPmessagePrintWarning(
419  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
420  	   const char*           formatstr,          /**< format string like in printf() function */
421  	   ...                                       /**< format arguments line in printf() function */
422  	   )
423  	{
424  	   va_list ap;
425  	
426  	   va_start(ap, formatstr); /*lint !e838*/
427  	   SCIPmessageVFPrintWarning(messagehdlr, formatstr, ap);
428  	   va_end(ap);
429  	}
430  	
431  	/** prints a warning message, acting like the vprintf() command */
432  	void SCIPmessageVPrintWarning(
433  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
434  	   const char*           formatstr,          /**< format string like in printf() function */
435  	   va_list               ap                  /**< variable argument list */
436  	   )
437  	{
438  	   SCIPmessageVFPrintWarning(messagehdlr, formatstr, ap);
439  	}
440  	
441  	/** prints a warning message, acting like the fprintf() command */
442  	void SCIPmessageFPrintWarning(
443  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
444  	   const char*           formatstr,          /**< format string like in printf() function */
445  	   ...                                       /**< format arguments line in printf() function */
446  	   )
447  	{
448  	   va_list ap;
449  	
450  	   va_start(ap, formatstr); /*lint !e838*/
451  	   SCIPmessageVFPrintWarning(messagehdlr, formatstr, ap);
452  	   va_end(ap);
453  	}
454  	
455  	/** prints a warning message, acting like the vfprintf() command */
456  	void SCIPmessageVFPrintWarning(
457  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
458  	   const char*           formatstr,          /**< format string like in printf() function */
459  	   va_list               ap                  /**< variable argument list */
460  	   )
461  	{
462  	   char msg[SCIP_MAXSTRLEN];
463  	   int n;
464  	   va_list aq;
465  	
466  	   va_copy(aq, ap); /*lint !e838*/
467  	
468  	   n = vsnprintf(msg, SCIP_MAXSTRLEN, formatstr, ap);
469  	   if( n < 0 )
470  	      msg[SCIP_MAXSTRLEN-1] = '\0';
471  	   else if( n >= SCIP_MAXSTRLEN )
472  	   {
473  	      char* bigmsg;
474  	#ifndef NDEBUG
475  	      int m;
476  	#endif
477  	
478  	      if( BMSallocMemorySize(&bigmsg, n+1) == NULL )
479  	      {
480  	         va_end(aq);
481  	         return;
482  	      }
483  	
484  	#ifndef NDEBUG
485  	      m = vsnprintf(bigmsg, (size_t) n+1, formatstr, aq); /*lint !e571*/
486  	#else
487  	      vsnprintf(bigmsg, (size_t) n+1, formatstr, aq); /*lint !e571*/
488  	#endif
489  	      assert(m == n);
490  	      va_end(aq);
491  	      messagePrintWarning(messagehdlr, bigmsg);
492  	      BMSfreeMemory(&bigmsg);
493  	      return;
494  	   }
495  	
496  	   messagePrintWarning(messagehdlr, msg);
497  	   va_end(aq);
498  	}
499  	
500  	/** prints a dialog message that requests user interaction, acting like the printf() command */
501  	void SCIPmessagePrintDialog(
502  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
503  	   const char*           formatstr,          /**< format string like in printf() function */
504  	   ...                                       /**< format arguments line in printf() function */
505  	   )
506  	{
507  	   va_list ap;
508  	
509  	   va_start(ap, formatstr); /*lint !e838*/
510  	   SCIPmessageVFPrintDialog(messagehdlr, NULL, formatstr, ap);
511  	   va_end(ap);
512  	}
513  	
514  	/** prints a dialog message that requests user interaction, acting like the vprintf() command */
515  	void SCIPmessageVPrintDialog(
516  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
517  	   const char*           formatstr,          /**< format string like in printf() function */
518  	   va_list               ap                  /**< variable argument list */
519  	   )
520  	{
521  	   SCIPmessageVFPrintDialog(messagehdlr, NULL, formatstr, ap);
522  	}
523  	
524  	/** prints a dialog message that requests user interaction into a file, acting like the fprintf() command */
525  	void SCIPmessageFPrintDialog(
526  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
527  	   FILE*                 file,               /**< file stream to print into, or NULL for stdout */
528  	   const char*           formatstr,          /**< format string like in printf() function */
529  	   ...                                       /**< format arguments line in printf() function */
530  	   )
531  	{
532  	   va_list ap;
533  	
534  	   va_start(ap, formatstr); /*lint !e838*/
535  	   SCIPmessageVFPrintDialog(messagehdlr, file, formatstr, ap);
536  	   va_end(ap);
537  	}
538  	
539  	/** prints a dialog message that requests user interaction into a file, acting like the vfprintf() command */
540  	void SCIPmessageVFPrintDialog(
541  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
542  	   FILE*                 file,               /**< file stream to print into, or NULL for stdout */
543  	   const char*           formatstr,          /**< format string like in printf() function */
544  	   va_list               ap                  /**< variable argument list */
545  	   )
546  	{
547  	   char msg[SCIP_MAXSTRLEN];
548  	   int n;
549  	   va_list aq;
550  	
551  	   va_copy(aq, ap); /*lint !e838*/
552  	
553  	   n = vsnprintf(msg, SCIP_MAXSTRLEN, formatstr, ap);
554  	   if( n < 0 )
555  	      msg[SCIP_MAXSTRLEN-1] = '\0';
556  	   else if( n >= SCIP_MAXSTRLEN )
557  	   {
558  	      char* bigmsg;
559  	#ifndef NDEBUG
560  	      int m;
561  	#endif
562  	
563  	      if( BMSallocMemorySize(&bigmsg, n+1) == NULL )
564  	      {
565  	         va_end(aq);
566  	         return;
567  	      }
568  	
569  	#ifndef NDEBUG
570  	      m = vsnprintf(bigmsg, (size_t) n+1, formatstr, aq); /*lint !e571*/
571  	#else
572  	      vsnprintf(bigmsg, (size_t) n+1, formatstr, aq); /*lint !e571*/
573  	#endif
574  	      assert(m == n);
575  	      va_end(aq);
576  	      messagePrintDialog(messagehdlr, file, bigmsg);
577  	      BMSfreeMemory(&bigmsg);
578  	      return;
579  	   }
580  	   messagePrintDialog(messagehdlr, file, msg);
581  	   va_end(aq);
582  	}
583  	
584  	/** prints a message, acting like the printf() command */
585  	void SCIPmessagePrintInfo(
586  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
587  	   const char*           formatstr,          /**< format string like in printf() function */
588  	   ...                                       /**< format arguments line in printf() function */
589  	   )
590  	{
591  	   va_list ap;
592  	
593  	   va_start(ap, formatstr); /*lint !e838*/
594  	   SCIPmessageVFPrintInfo(messagehdlr, NULL, formatstr, ap);
595  	   va_end(ap);
596  	}
597  	
598  	/** prints a message, acting like the vprintf() command */
599  	void SCIPmessageVPrintInfo(
600  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
601  	   const char*           formatstr,          /**< format string like in printf() function */
602  	   va_list               ap                  /**< variable argument list */
603  	   )
604  	{
605  	   SCIPmessageVFPrintInfo(messagehdlr, NULL, formatstr, ap);
606  	}
607  	
608  	/** prints a message into a file, acting like the fprintf() command */
609  	void SCIPmessageFPrintInfo(
610  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
(1) Event noescape: "SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *, FILE *, char const *, ...)" does not free or save its parameter "file".
(1) Event noescape: "SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *, FILE *, char const *, ...)" does not free or save its parameter "file".
(1) Event noescape: "SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *, FILE *, char const *, ...)" does not free or save its parameter "file".
(1) Event noescape: "SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *, FILE *, char const *, ...)" does not free or save its parameter "file".
(1) Event noescape: "SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *, FILE *, char const *, ...)" does not free or save its parameter "file".
(1) Event noescape: "SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *, FILE *, char const *, ...)" does not free or save its parameter "file".
(1) Event noescape: "SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *, FILE *, char const *, ...)" does not free or save its parameter "file".
611  	   FILE*                 file,               /**< file stream to print into, or NULL for stdout */
612  	   const char*           formatstr,          /**< format string like in printf() function */
613  	   ...                                       /**< format arguments line in printf() function */
614  	   )
615  	{
616  	   va_list ap;
617  	
618  	   va_start(ap, formatstr); /*lint !e838*/
619  	   SCIPmessageVFPrintInfo(messagehdlr, file, formatstr, ap);
620  	   va_end(ap);
621  	}
622  	
623  	/** prints a message into a file, acting like the vfprintf() command */
624  	void SCIPmessageVFPrintInfo(
625  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
626  	   FILE*                 file,               /**< file stream to print into, or NULL for stdout */
627  	   const char*           formatstr,          /**< format string like in printf() function */
628  	   va_list               ap                  /**< variable argument list */
629  	   )
630  	{
631  	   char msg[SCIP_MAXSTRLEN];
632  	   int n;
633  	   va_list aq;
634  	
635  	   va_copy(aq, ap); /*lint !e838*/
636  	
637  	   n = vsnprintf(msg, SCIP_MAXSTRLEN, formatstr, ap);
638  	   if( n < 0 )
639  	      msg[SCIP_MAXSTRLEN-1] = '\0';
640  	   else if( n >= SCIP_MAXSTRLEN )
641  	   {
642  	      char* bigmsg;
643  	#ifndef NDEBUG
644  	      int m;
645  	#endif
646  	
647  	      if( BMSallocMemorySize(&bigmsg, n+1) == NULL )
648  	      {
649  	         va_end(aq);
650  	         return;
651  	      }
652  	
653  	#ifndef NDEBUG
654  	      m = vsnprintf(bigmsg, (size_t) n+1, formatstr, aq); /*lint !e571*/
655  	#else
656  	      vsnprintf(bigmsg, (size_t) n+1, formatstr, aq); /*lint !e571*/
657  	#endif
658  	      assert(m == n);
659  	      va_end(aq);
660  	      messagePrintInfo(messagehdlr, file, bigmsg);
661  	      BMSfreeMemory(&bigmsg);
662  	      return;
663  	   }
664  	   messagePrintInfo(messagehdlr, file, msg);
665  	   va_end(aq);
666  	}
667  	
668  	/** prints a message depending on the verbosity level, acting like the printf() command */
669  	void SCIPmessagePrintVerbInfo(
670  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
671  	   SCIP_VERBLEVEL        verblevel,          /**< current verbosity level */
672  	   SCIP_VERBLEVEL        msgverblevel,       /**< verbosity level of this message */
673  	   const char*           formatstr,          /**< format string like in printf() function */
674  	   ...                                       /**< format arguments line in printf() function */
675  	   )
676  	{
677  	   va_list ap;
678  	
679  	   va_start(ap, formatstr); /*lint !e838*/
680  	   SCIPmessageVFPrintVerbInfo(messagehdlr, verblevel, msgverblevel, NULL, formatstr, ap);
681  	   va_end(ap);
682  	}
683  	
684  	/** prints a message depending on the verbosity level, acting like the vprintf() command */
685  	void SCIPmessageVPrintVerbInfo(
686  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
687  	   SCIP_VERBLEVEL        verblevel,          /**< current verbosity level */
688  	   SCIP_VERBLEVEL        msgverblevel,       /**< verbosity level of this message */
689  	   const char*           formatstr,          /**< format string like in printf() function */
690  	   va_list               ap                  /**< variable argument list */
691  	   )
692  	{
693  	   SCIPmessageVFPrintVerbInfo(messagehdlr, verblevel, msgverblevel, NULL, formatstr, ap);
694  	}
695  	
696  	/** prints a message into a file depending on the verbosity level, acting like the fprintf() command */
697  	void SCIPmessageFPrintVerbInfo(
698  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
699  	   SCIP_VERBLEVEL        verblevel,          /**< current verbosity level */
700  	   SCIP_VERBLEVEL        msgverblevel,       /**< verbosity level of this message */
701  	   FILE*                 file,               /**< file stream to print into, or NULL for stdout */
702  	   const char*           formatstr,          /**< format string like in printf() function */
703  	   ...                                       /**< format arguments line in printf() function */
704  	   )
705  	{
706  	   va_list ap;
707  	
708  	   va_start(ap, formatstr); /*lint !e838*/
709  	   SCIPmessageVFPrintVerbInfo(messagehdlr, verblevel, msgverblevel, file, formatstr, ap);
710  	   va_end(ap);
711  	}
712  	
713  	/** prints a message into a file depending on the verbosity level, acting like the vfprintf() command */
714  	void SCIPmessageVFPrintVerbInfo(
715  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
716  	   SCIP_VERBLEVEL        verblevel,          /**< current verbosity level */
717  	   SCIP_VERBLEVEL        msgverblevel,       /**< verbosity level of this message */
718  	   FILE*                 file,               /**< file stream to print into, or NULL for stdout */
719  	   const char*           formatstr,          /**< format string like in printf() function */
720  	   va_list               ap                  /**< variable argument list */
721  	   )
722  	{
723  	   assert(msgverblevel > SCIP_VERBLEVEL_NONE);
724  	   assert(msgverblevel <= SCIP_VERBLEVEL_FULL);
725  	   assert(verblevel <= SCIP_VERBLEVEL_FULL);
726  	
727  	   if( msgverblevel <= verblevel )
728  	   {
729  	      char msg[SCIP_MAXSTRLEN];
730  	      int n;
731  	      va_list aq;
732  	
733  	      va_copy(aq, ap); /*lint !e838*/
734  	
735  	      n = vsnprintf(msg, SCIP_MAXSTRLEN, formatstr, ap);
736  	      if( n < 0 )
737  	         msg[SCIP_MAXSTRLEN-1] = '\0';
738  	      else if( n >= SCIP_MAXSTRLEN )
739  	      {
740  	         char* bigmsg;
741  	#ifndef NDEBUG
742  	         int m;
743  	#endif
744  	
745  	         if( BMSallocMemorySize(&bigmsg, n+1) == NULL )
746  	         {
747  	            va_end(aq);
748  	            return;
749  	         }
750  	
751  	#ifndef NDEBUG
752  	         m = vsnprintf(bigmsg, (size_t) n+1, formatstr, aq); /*lint !e571*/
753  	#else
754  	         vsnprintf(bigmsg, (size_t) n+1, formatstr, aq); /*lint !e571*/
755  	#endif
756  	         assert(m == n);
757  	         va_end(aq);
758  	         messagePrintInfo(messagehdlr, file, bigmsg);
759  	         BMSfreeMemory(&bigmsg);
760  	         return;
761  	      }
762  	      messagePrintInfo(messagehdlr, file, msg);
763  	      va_end(aq);
764  	   }
765  	}
766  	
767  	/** prints the header with source file location for an error message using the static message handler */
768  	void SCIPmessagePrintErrorHeader(
769  	   const char*           sourcefile,         /**< name of the source file that called the function */
770  	   int                   sourceline          /**< line in the source file where the function was called */
771  	   )
772  	{
773  	   char msg[SCIP_MAXSTRLEN];
774  	
775  	   /* safe string printing - do not use SCIPsnprintf() since message.c should be independent */
776  	   (void) snprintf(msg, SCIP_MAXSTRLEN, "[%s:%d] ERROR: ", sourcefile, sourceline);
777  	   msg[SCIP_MAXSTRLEN-1] = '\0';
778  	   messagePrintError(NULL, msg);
779  	}
780  	
781  	/** prints a error message, acting like the printf() command */
782  	void SCIPmessagePrintError(
783  	   const char*           formatstr,          /**< format string like in printf() function */
784  	   ...                                       /**< format arguments line in printf() function */
785  	   )
786  	{
787  	   va_list ap;
788  	
789  	   va_start(ap, formatstr); /*lint !e838*/
790  	   SCIPmessageVPrintError(formatstr, ap);
791  	   va_end(ap);
792  	}
793  	
794  	/** prints an error message, acting like the vprintf() command using the static message handler */
795  	void SCIPmessageVPrintError(
796  	   const char*           formatstr,          /**< format string like in printf() function */
797  	   va_list               ap                  /**< variable argument list */
798  	   )
799  	{
800  	   char msg[SCIP_MAXSTRLEN];
801  	   int n;
802  	   va_list aq;
803  	
804  	   va_copy(aq, ap); /*lint !e838*/
805  	
806  	   n = vsnprintf(msg, SCIP_MAXSTRLEN, formatstr, ap);
807  	   if( n < 0 )
808  	      msg[SCIP_MAXSTRLEN-1] = '\0';
809  	   else if( n >= SCIP_MAXSTRLEN )
810  	   {
811  	      char* bigmsg;
812  	#ifndef NDEBUG
813  	      int m;
814  	#endif
815  	
816  	      if( BMSallocMemorySize(&bigmsg, n+1) == NULL )
817  	      {
818  	         va_end(aq);
819  	         return;
820  	      }
821  	
822  	#ifndef NDEBUG
823  	      m = vsnprintf(bigmsg, (size_t) n+1, formatstr, aq); /*lint !e571*/
824  	#else
825  	      vsnprintf(bigmsg, (size_t) n+1, formatstr, aq); /*lint !e571*/
826  	#endif
827  	      assert(m == n);
828  	      va_end(aq);
829  	      messagePrintError(NULL, bigmsg);
830  	      BMSfreeMemory(&bigmsg);
831  	      return;
832  	   }
833  	
834  	   messagePrintError(NULL, msg);
835  	   va_end(aq);
836  	}
837  	
838  	/** Method to set the error printing method. Setting the error printing method to NULL will suspend all error methods.
839  	 *
840  	 *  @note The error printing method is static variable. That means all occurring errors are handled via that methods
841  	 */
842  	void SCIPmessageSetErrorPrinting(
843  	   SCIP_DECL_ERRORPRINTING((*errorPrinting)),/**< error message print method of message handler, or NULL */
844  	   void*                 data                /**< data pointer which will be passed to the error printing method, or NULL */
845  	   )
846  	{
847  	   staticErrorPrinting = errorPrinting;
848  	   staticErrorPrintingData = data;
849  	}
850  	
851  	/** Method to set the error printing method to default version prints everything the stderr.
852  	 *
853  	 *  @note The error printing method is a static variable. This means that all occurring errors are handled via this method.
854  	 */
855  	void SCIPmessageSetErrorPrintingDefault(
856  	   void
857  	   )
858  	{
859  	   staticErrorPrinting = errorPrintingDefault;
860  	   staticErrorPrintingData = NULL;
861  	}
862  	
863  	/*
864  	 * simple functions implemented as defines
865  	 */
866  	
867  	/* In debug mode, the following methods are implemented as function calls to ensure
868  	 * type validity.
869  	 * In optimized mode, the methods are implemented as defines to improve performance.
870  	 * However, we want to have them in the library anyways, so we have to undef the defines.
871  	 */
872  	
873  	#undef SCIPmessagehdlrGetData
874  	#undef SCIPmessagehdlrGetLogfile
875  	#undef SCIPmessagehdlrIsQuiet
876  	
877  	/** returns the user data of the message handler */
878  	SCIP_MESSAGEHDLRDATA* SCIPmessagehdlrGetData(
879  	   SCIP_MESSAGEHDLR*     messagehdlr         /**< message handler */
880  	   )
881  	{
882  	   if( messagehdlr != NULL )
883  	      return messagehdlr->messagehdlrdata;
884  	   else
885  	      return NULL;
886  	}
887  	
888  	
889  	/** returns the log file or NULL for stdout */
890  	FILE* SCIPmessagehdlrGetLogfile(
891  	   SCIP_MESSAGEHDLR*     messagehdlr         /**< message handler */
892  	   )
893  	{
894  	   if( messagehdlr == NULL )
895  	      return NULL;
896  	
897  	   return messagehdlr->logfile;
898  	}
899  	
900  	/** returns TRUE if the message handler is set to be quiet */
901  	SCIP_Bool SCIPmessagehdlrIsQuiet(
902  	   SCIP_MESSAGEHDLR*     messagehdlr         /**< message handler */
903  	   )
904  	{
905  	   return (messagehdlr == NULL || messagehdlr->quiet);
906  	}
907