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
handleMessage(SCIP_MESSAGEHDLR * messagehdlr,SCIP_DECL_MESSAGEOUTPUTFUNC (outputfunc),FILE * file1,SCIP_Bool usefile1,FILE * file2,SCIP_Bool usefile2,const char * msg,char * buffer,int * bufferlen)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
SCIP_DECL_ERRORPRINTING(errorPrintingDefault)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
messagePrintError(FILE * file,const char * msg)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
messagePrintWarning(SCIP_MESSAGEHDLR * messagehdlr,const char * msg)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
messagePrintDialog(SCIP_MESSAGEHDLR * messagehdlr,FILE * file,const char * msg)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
messagePrintInfo(SCIP_MESSAGEHDLR * messagehdlr,FILE * file,const char * msg)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
messagehdlrOpenLogfile(SCIP_MESSAGEHDLR * messagehdlr,const char * filename)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
messagehdlrFree(SCIP_MESSAGEHDLR ** messagehdlr)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 */
SCIPmessagehdlrCreate(SCIP_MESSAGEHDLR ** messagehdlr,SCIP_Bool bufferedoutput,const char * filename,SCIP_Bool quiet,SCIP_DECL_MESSAGEWARNING ((* messagewarning)),SCIP_DECL_MESSAGEDIALOG ((* messagedialog)),SCIP_DECL_MESSAGEINFO ((* messageinfo)),SCIP_DECL_MESSAGEHDLRFREE ((* messagehdlrfree)),SCIP_MESSAGEHDLRDATA * messagehdlrdata)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 */
SCIPmessagehdlrCapture(SCIP_MESSAGEHDLR * messagehdlr)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 */
SCIPmessagehdlrRelease(SCIP_MESSAGEHDLR ** messagehdlr)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 */
SCIPmessagehdlrSetData(SCIP_MESSAGEHDLR * messagehdlr,SCIP_MESSAGEHDLRDATA * messagehdlrdata)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 */
SCIPmessagehdlrSetLogfile(SCIP_MESSAGEHDLR * messagehdlr,const char * filename)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 */
SCIPmessagehdlrSetQuiet(SCIP_MESSAGEHDLR * messagehdlr,SCIP_Bool 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 */
SCIPmessagePrintWarning(SCIP_MESSAGEHDLR * messagehdlr,const char * formatstr,...)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 */
SCIPmessageVPrintWarning(SCIP_MESSAGEHDLR * messagehdlr,const char * formatstr,va_list ap)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 */
SCIPmessageFPrintWarning(SCIP_MESSAGEHDLR * messagehdlr,const char * formatstr,...)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 */
SCIPmessageVFPrintWarning(SCIP_MESSAGEHDLR * messagehdlr,const char * formatstr,va_list ap)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 */
SCIPmessagePrintDialog(SCIP_MESSAGEHDLR * messagehdlr,const char * formatstr,...)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 */
SCIPmessageVPrintDialog(SCIP_MESSAGEHDLR * messagehdlr,const char * formatstr,va_list ap)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 */
SCIPmessageFPrintDialog(SCIP_MESSAGEHDLR * messagehdlr,FILE * file,const char * formatstr,...)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 */
SCIPmessageVFPrintDialog(SCIP_MESSAGEHDLR * messagehdlr,FILE * file,const char * formatstr,va_list ap)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 */
SCIPmessagePrintInfo(SCIP_MESSAGEHDLR * messagehdlr,const char * formatstr,...)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 */
SCIPmessageVPrintInfo(SCIP_MESSAGEHDLR * messagehdlr,const char * formatstr,va_list ap)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 */
SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR * messagehdlr,FILE * file,const char * formatstr,...)609 void SCIPmessageFPrintInfo(
610 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
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 */
SCIPmessageVFPrintInfo(SCIP_MESSAGEHDLR * messagehdlr,FILE * file,const char * formatstr,va_list ap)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 */
SCIPmessagePrintVerbInfo(SCIP_MESSAGEHDLR * messagehdlr,SCIP_VERBLEVEL verblevel,SCIP_VERBLEVEL msgverblevel,const char * formatstr,...)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 */
SCIPmessageVPrintVerbInfo(SCIP_MESSAGEHDLR * messagehdlr,SCIP_VERBLEVEL verblevel,SCIP_VERBLEVEL msgverblevel,const char * formatstr,va_list ap)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 */
SCIPmessageFPrintVerbInfo(SCIP_MESSAGEHDLR * messagehdlr,SCIP_VERBLEVEL verblevel,SCIP_VERBLEVEL msgverblevel,FILE * file,const char * formatstr,...)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 */
SCIPmessageVFPrintVerbInfo(SCIP_MESSAGEHDLR * messagehdlr,SCIP_VERBLEVEL verblevel,SCIP_VERBLEVEL msgverblevel,FILE * file,const char * formatstr,va_list ap)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 */
SCIPmessagePrintErrorHeader(const char * sourcefile,int sourceline)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 */
SCIPmessagePrintError(const char * formatstr,...)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 */
SCIPmessageVPrintError(const char * formatstr,va_list ap)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 */
SCIPmessageSetErrorPrinting(SCIP_DECL_ERRORPRINTING ((* errorPrinting)),void * data)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 */
SCIPmessageSetErrorPrintingDefault(void)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 */
SCIPmessagehdlrGetData(SCIP_MESSAGEHDLR * messagehdlr)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 */
SCIPmessagehdlrGetLogfile(SCIP_MESSAGEHDLR * messagehdlr)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 */
SCIPmessagehdlrIsQuiet(SCIP_MESSAGEHDLR * messagehdlr)901 SCIP_Bool SCIPmessagehdlrIsQuiet(
902 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
903 )
904 {
905 return (messagehdlr == NULL || messagehdlr->quiet);
906 }
907