blob: 41171267d44bddfb9518aa3541976e0a776e6d4f [file] [log] [blame]
njnc44a6c22005-06-03 13:21:18 +00001
2/*--------------------------------------------------------------------*/
3/*--- Libc printing. m_libcprint.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
sewardj9eecbbb2010-05-03 21:37:12 +000010 Copyright (C) 2000-2010 Julian Seward
njnc44a6c22005-06-03 13:21:18 +000011 jseward@acm.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
sewardj4cfea4f2006-10-14 19:26:10 +000032#include "pub_core_vki.h"
njnc44a6c22005-06-03 13:21:18 +000033#include "pub_core_debuglog.h"
34#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000035#include "pub_core_libcassert.h"
sewardj592ae092005-11-08 19:01:44 +000036#include "pub_core_libcfile.h" // VG_(write)(), VG_(write_socket)()
njnc44a6c22005-06-03 13:21:18 +000037#include "pub_core_libcprint.h"
sewardj592ae092005-11-08 19:01:44 +000038#include "pub_core_libcproc.h" // VG_(getpid)(), VG_(read_millisecond_timer()
njnc44a6c22005-06-03 13:21:18 +000039#include "pub_core_options.h"
njn24a6efb2005-06-20 03:36:51 +000040#include "valgrind.h" // For RUNNING_ON_VALGRIND
njnc44a6c22005-06-03 13:21:18 +000041
njnc44a6c22005-06-03 13:21:18 +000042
43/* ---------------------------------------------------------------------
44 Writing to file or a socket
45 ------------------------------------------------------------------ */
46
sewardj738856f2009-07-15 14:48:32 +000047/* The destination sinks for normal and XML output. These have their
48 initial values here; they are set to final values by
49 m_main.main_process_cmd_line_options(). See comment at the top of
50 that function for the associated logic. */
51OutputSink VG_(log_output_sink) = { 2, False }; /* 2 = stderr */
52OutputSink VG_(xml_output_sink) = { -1, False }; /* disabled */
53
njnc44a6c22005-06-03 13:21:18 +000054/* Do the low-level send of a message to the logging sink. */
sewardj738856f2009-07-15 14:48:32 +000055static
56void send_bytes_to_logging_sink ( OutputSink* sink, Char* msg, Int nbytes )
njnc44a6c22005-06-03 13:21:18 +000057{
sewardj738856f2009-07-15 14:48:32 +000058 if (sink->is_socket) {
59 Int rc = VG_(write_socket)( sink->fd, msg, nbytes );
60 if (rc == -1) {
61 // For example, the listener process died. Switch back to stderr.
62 sink->is_socket = False;
63 sink->fd = 2;
64 VG_(write)( sink->fd, msg, nbytes );
65 }
66 } else {
67 /* sink->fd could have been set to -1 in the various
sewardj6e31f802007-11-17 22:29:25 +000068 sys-wrappers for sys_fork, if --child-silent-after-fork=yes
69 is in effect. That is a signal that we should not produce
70 any more output. */
sewardj738856f2009-07-15 14:48:32 +000071 if (sink->fd >= 0)
72 VG_(write)( sink->fd, msg, nbytes );
njnc44a6c22005-06-03 13:21:18 +000073 }
74}
75
sewardj738856f2009-07-15 14:48:32 +000076
njnc44a6c22005-06-03 13:21:18 +000077/* ---------------------------------------------------------------------
78 printf() and friends
79 ------------------------------------------------------------------ */
80
sewardj738856f2009-07-15 14:48:32 +000081/* --------- printf --------- */
82
sewardj45f4e7c2005-09-27 19:20:21 +000083typedef
84 struct {
sewardj738856f2009-07-15 14:48:32 +000085 HChar buf[512];
86 Int buf_used;
87 OutputSink* sink;
sewardj45f4e7c2005-09-27 19:20:21 +000088 }
sewardj738856f2009-07-15 14:48:32 +000089 printf_buf_t;
bart1a0cb6a2008-04-14 16:35:32 +000090
njnc44a6c22005-06-03 13:21:18 +000091// Adds a single char to the buffer. When the buffer gets sufficiently
92// full, we write its contents to the logging sink.
sewardj738856f2009-07-15 14:48:32 +000093static void add_to__printf_buf ( HChar c, void *p )
njnc44a6c22005-06-03 13:21:18 +000094{
sewardj738856f2009-07-15 14:48:32 +000095 printf_buf_t *b = (printf_buf_t *)p;
njnc44a6c22005-06-03 13:21:18 +000096
sewardj738856f2009-07-15 14:48:32 +000097 if (b->buf_used > sizeof(b->buf) - 2 ) {
98 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
99 b->buf_used = 0;
njnc44a6c22005-06-03 13:21:18 +0000100 }
sewardj738856f2009-07-15 14:48:32 +0000101 b->buf[b->buf_used++] = c;
102 b->buf[b->buf_used] = 0;
103 tl_assert(b->buf_used < sizeof(b->buf));
104}
105
106static UInt vprintf_to_buf ( printf_buf_t* b,
107 const HChar *format, va_list vargs )
108{
109 UInt ret = 0;
110 if (b->sink->fd >= 0) {
111 ret = VG_(debugLog_vprintf)
112 ( add_to__printf_buf, b, format, vargs );
113 }
114 return ret;
115}
116
117static UInt vprintf_WRK ( OutputSink* sink,
118 const HChar *format, va_list vargs )
119{
120 printf_buf_t myprintf_buf
121 = { "", 0, sink };
122 UInt ret
123 = vprintf_to_buf(&myprintf_buf, format, vargs);
124 // Write out any chars left in the buffer.
125 if (myprintf_buf.buf_used > 0) {
126 send_bytes_to_logging_sink( myprintf_buf.sink,
127 myprintf_buf.buf,
128 myprintf_buf.buf_used );
129 }
130 return ret;
njnc44a6c22005-06-03 13:21:18 +0000131}
132
133UInt VG_(vprintf) ( const HChar *format, va_list vargs )
134{
sewardj738856f2009-07-15 14:48:32 +0000135 return vprintf_WRK( &VG_(log_output_sink), format, vargs );
njnc44a6c22005-06-03 13:21:18 +0000136}
137
138UInt VG_(printf) ( const HChar *format, ... )
139{
140 UInt ret;
141 va_list vargs;
njnc44a6c22005-06-03 13:21:18 +0000142 va_start(vargs, format);
143 ret = VG_(vprintf)(format, vargs);
144 va_end(vargs);
njnc44a6c22005-06-03 13:21:18 +0000145 return ret;
146}
147
sewardj738856f2009-07-15 14:48:32 +0000148UInt VG_(vprintf_xml) ( const HChar *format, va_list vargs )
149{
150 return vprintf_WRK( &VG_(xml_output_sink), format, vargs );
151}
152
153UInt VG_(printf_xml) ( const HChar *format, ... )
bart1a0cb6a2008-04-14 16:35:32 +0000154{
155 UInt ret;
156 va_list vargs;
bart1a0cb6a2008-04-14 16:35:32 +0000157 va_start(vargs, format);
sewardj738856f2009-07-15 14:48:32 +0000158 ret = VG_(vprintf_xml)(format, vargs);
bart1a0cb6a2008-04-14 16:35:32 +0000159 va_end(vargs);
bart1a0cb6a2008-04-14 16:35:32 +0000160 return ret;
161}
162
sewardj738856f2009-07-15 14:48:32 +0000163/* An exact clone of VG_(printf_xml), unfortunately. */
164UInt VG_(printf_xml_no_f_c) ( const HChar *format, ... )
njnc44a6c22005-06-03 13:21:18 +0000165{
sewardj738856f2009-07-15 14:48:32 +0000166 UInt ret;
167 va_list vargs;
168 va_start(vargs, format);
169 ret = VG_(vprintf_xml)(format, vargs);
170 va_end(vargs);
171 return ret;
172}
173
174
175/* --------- sprintf --------- */
176
177/* If we had an explicit buf structure here, it would contain only one
178 field, indicating where the next char is to go. So use p directly
179 for that, rather than having it be a pointer to a structure. */
180
181static void add_to__sprintf_buf ( HChar c, void *p )
182{
183 HChar** b = p;
184 *(*b)++ = c;
njnc44a6c22005-06-03 13:21:18 +0000185}
186
187UInt VG_(vsprintf) ( Char* buf, const HChar *format, va_list vargs )
188{
189 Int ret;
sewardj738856f2009-07-15 14:48:32 +0000190 HChar* sprintf_ptr = buf;
njnc44a6c22005-06-03 13:21:18 +0000191
192 ret = VG_(debugLog_vprintf)
sewardj738856f2009-07-15 14:48:32 +0000193 ( add_to__sprintf_buf, &sprintf_ptr, format, vargs );
194 add_to__sprintf_buf('\0', &sprintf_ptr);
njnc44a6c22005-06-03 13:21:18 +0000195
196 vg_assert(VG_(strlen)(buf) == ret);
197
198 return ret;
199}
200
201UInt VG_(sprintf) ( Char* buf, const HChar *format, ... )
202{
203 UInt ret;
204 va_list vargs;
njnc44a6c22005-06-03 13:21:18 +0000205 va_start(vargs,format);
206 ret = VG_(vsprintf)(buf, format, vargs);
207 va_end(vargs);
njnc44a6c22005-06-03 13:21:18 +0000208 return ret;
209}
210
sewardj45f4e7c2005-09-27 19:20:21 +0000211
sewardj738856f2009-07-15 14:48:32 +0000212/* --------- snprintf --------- */
213
sewardj45f4e7c2005-09-27 19:20:21 +0000214typedef
215 struct {
216 HChar* buf;
217 Int buf_size;
218 Int buf_used;
219 }
sewardj738856f2009-07-15 14:48:32 +0000220 snprintf_buf_t;
sewardj45f4e7c2005-09-27 19:20:21 +0000221
sewardj738856f2009-07-15 14:48:32 +0000222static void add_to__snprintf_buf ( HChar c, void* p )
sewardj45f4e7c2005-09-27 19:20:21 +0000223{
sewardj738856f2009-07-15 14:48:32 +0000224 snprintf_buf_t* b = p;
sewardj45f4e7c2005-09-27 19:20:21 +0000225 if (b->buf_size > 0 && b->buf_used < b->buf_size) {
226 b->buf[b->buf_used++] = c;
227 if (b->buf_used < b->buf_size)
228 b->buf[b->buf_used] = 0;
sewardj03e2bb82006-12-24 03:02:18 +0000229 else
230 b->buf[b->buf_size-1] = 0; /* pre: b->buf_size > 0 */
sewardj45f4e7c2005-09-27 19:20:21 +0000231 }
232}
233
234UInt VG_(vsnprintf) ( Char* buf, Int size, const HChar *format, va_list vargs )
235{
236 Int ret;
sewardj738856f2009-07-15 14:48:32 +0000237 snprintf_buf_t b;
sewardj45f4e7c2005-09-27 19:20:21 +0000238 b.buf = buf;
239 b.buf_size = size < 0 ? 0 : size;
240 b.buf_used = 0;
241
242 ret = VG_(debugLog_vprintf)
sewardj738856f2009-07-15 14:48:32 +0000243 ( add_to__snprintf_buf, &b, format, vargs );
sewardj45f4e7c2005-09-27 19:20:21 +0000244
245 return b.buf_used;
246}
247
248UInt VG_(snprintf) ( Char* buf, Int size, const HChar *format, ... )
249{
250 UInt ret;
251 va_list vargs;
sewardj45f4e7c2005-09-27 19:20:21 +0000252 va_start(vargs,format);
253 ret = VG_(vsnprintf)(buf, size, format, vargs);
254 va_end(vargs);
sewardj45f4e7c2005-09-27 19:20:21 +0000255 return ret;
256}
257
258
sewardj738856f2009-07-15 14:48:32 +0000259/* --------- vcbprintf --------- */
260
261void VG_(vcbprintf)( void(*char_sink)(HChar, void* opaque),
262 void* opaque,
263 const HChar* format, va_list vargs )
264{
265 (void) VG_(debugLog_vprintf)
266 ( char_sink, opaque, format, vargs );
267}
268
269
njnc44a6c22005-06-03 13:21:18 +0000270/* ---------------------------------------------------------------------
njn856c54e2005-06-26 18:43:40 +0000271 percentify()
272 ------------------------------------------------------------------ */
273
njn7a5915e2005-07-17 16:12:59 +0000274// Percentify n/m with d decimal places. Includes the '%' symbol at the end.
njn5eaff2f2005-09-25 19:11:45 +0000275// Right justifies in 'buf'.
276void VG_(percentify)(ULong n, ULong m, UInt d, Int n_buf, char buf[])
njn856c54e2005-06-26 18:43:40 +0000277{
278 Int i, len, space;
njn641e6162005-07-17 16:16:41 +0000279 ULong p1;
njn5eaff2f2005-09-25 19:11:45 +0000280 Char fmt[32];
njn856c54e2005-06-26 18:43:40 +0000281
njn641e6162005-07-17 16:16:41 +0000282 if (m == 0) {
njn5eaff2f2005-09-25 19:11:45 +0000283 // Have to generate the format string in order to be flexible about
284 // the width of the field.
njn8a7b41b2007-09-23 00:51:24 +0000285 VG_(sprintf)(fmt, "%%-%ds", n_buf);
njn5eaff2f2005-09-25 19:11:45 +0000286 // fmt is now "%<n_buf>s" where <d> is 1,2,3...
287 VG_(sprintf)(buf, fmt, "--%");
njn641e6162005-07-17 16:16:41 +0000288 return;
289 }
290
291 p1 = (100*n) / m;
njn856c54e2005-06-26 18:43:40 +0000292
293 if (d == 0) {
294 VG_(sprintf)(buf, "%lld%%", p1);
295 } else {
296 ULong p2;
297 UInt ex;
njn856c54e2005-06-26 18:43:40 +0000298 switch (d) {
299 case 1: ex = 10; break;
300 case 2: ex = 100; break;
301 case 3: ex = 1000; break;
302 default: VG_(tool_panic)("Currently can only handle 3 decimal places");
303 }
304 p2 = ((100*n*ex) / m) % ex;
305 // Have to generate the format string in order to be flexible about
306 // the width of the post-decimal-point part.
307 VG_(sprintf)(fmt, "%%lld.%%0%dlld%%%%", d);
308 // fmt is now "%lld.%0<d>lld%%" where <d> is 1,2,3...
309 VG_(sprintf)(buf, fmt, p1, p2);
310 }
311
312 len = VG_(strlen)(buf);
313 space = n_buf - len;
314 if (space < 0) space = 0; /* Allow for v. small field_width */
315 i = len;
316
317 /* Right justify in field */
318 for ( ; i >= 0; i--) buf[i + space] = buf[i];
319 for (i = 0; i < space; i++) buf[i] = ' ';
320}
321
sewardja11553a2005-07-19 12:17:05 +0000322
323/* ---------------------------------------------------------------------
sewardj592ae092005-11-08 19:01:44 +0000324 elapsed_wallclock_time()
sewardja11553a2005-07-19 12:17:05 +0000325 ------------------------------------------------------------------ */
326
sewardj592ae092005-11-08 19:01:44 +0000327/* Get the elapsed wallclock time since startup into buf, which must
328 16 chars long. This is unchecked. It also relies on the
329 millisecond timer having been set to zero by an initial read in
330 m_main during startup. */
sewardja11553a2005-07-19 12:17:05 +0000331
sewardj592ae092005-11-08 19:01:44 +0000332void VG_(elapsed_wallclock_time) ( /*OUT*/HChar* buf )
sewardja11553a2005-07-19 12:17:05 +0000333{
sewardj592ae092005-11-08 19:01:44 +0000334 UInt t, ms, s, mins, hours, days;
335
336 t = VG_(read_millisecond_timer)(); /* milliseconds */
337
338 ms = t % 1000;
339 t /= 1000; /* now in seconds */
340
341 s = t % 60;
342 t /= 60; /* now in minutes */
343
344 mins = t % 60;
345 t /= 60; /* now in hours */
346
347 hours = t % 24;
348 t /= 24; /* now in days */
349
350 days = t;
351
njn82baca72009-07-24 05:35:49 +0000352 VG_(sprintf)(buf, "%02u:%02u:%02u:%02u.%03u ", days, hours, mins, s, ms);
sewardja11553a2005-07-19 12:17:05 +0000353}
354
355
njn856c54e2005-06-26 18:43:40 +0000356/* ---------------------------------------------------------------------
njnc44a6c22005-06-03 13:21:18 +0000357 message()
358 ------------------------------------------------------------------ */
359
sewardj738856f2009-07-15 14:48:32 +0000360/* A buffer for accumulating VG_(message) style output. This is
361 pretty much the same as VG_(printf)'s scheme, with two differences:
362
363 * The message buffer persists between calls, so that multiple
364 calls to VG_(message) can build up output.
365
366 * Whenever the first character on a line is emitted, the
367 ==PID== style preamble is stuffed in before it.
368*/
369typedef
370 struct {
371 HChar buf[512+128];
372 Int buf_used;
373 Bool atLeft; /* notionally, is the next char position at the
374 leftmost column? */
375 /* Current message kind - changes from call to call */
376 VgMsgKind kind;
sewardj738856f2009-07-15 14:48:32 +0000377 /* destination */
378 OutputSink* sink;
379 }
380 vmessage_buf_t;
381
382static vmessage_buf_t vmessage_buf
sewardj8ddb93a2010-02-15 10:07:05 +0000383 = { "", 0, True, Vg_UserMsg, &VG_(log_output_sink) };
sewardj738856f2009-07-15 14:48:32 +0000384
385
386// Adds a single char to the buffer. We aim to have at least 128
387// bytes free in the buffer, so that it's always possible to emit
388// the preamble into the buffer if c happens to be the character
389// following a \n. When the buffer gets too full, we write its
390// contents to the logging sink.
391static void add_to__vmessage_buf ( HChar c, void *p )
392{
393 HChar tmp[64];
394 vmessage_buf_t* b = (vmessage_buf_t*)p;
395
396 vg_assert(b->buf_used >= 0 && b->buf_used < sizeof(b->buf)-128);
397
398 if (UNLIKELY(b->atLeft)) {
399 // insert preamble
400 HChar ch;
401 Int i, depth;
402
sewardj738856f2009-07-15 14:48:32 +0000403 // Print one '>' in front of the messages for each level of
404 // self-hosting being performed.
405 depth = RUNNING_ON_VALGRIND;
406 if (depth > 10)
407 depth = 10; // ?!?!
408 for (i = 0; i < depth; i++) {
409 b->buf[b->buf_used++] = '>';
410 }
411
njnb1cc5d62010-07-06 04:05:23 +0000412 if (Vg_FailMsg == b->kind) {
413 // "valgrind: " prefix.
414 b->buf[b->buf_used++] = 'v';
415 b->buf[b->buf_used++] = 'a';
416 b->buf[b->buf_used++] = 'l';
417 b->buf[b->buf_used++] = 'g';
418 b->buf[b->buf_used++] = 'r';
419 b->buf[b->buf_used++] = 'i';
420 b->buf[b->buf_used++] = 'n';
421 b->buf[b->buf_used++] = 'd';
422 b->buf[b->buf_used++] = ':';
423 b->buf[b->buf_used++] = ' ';
424 } else {
425 switch (b->kind) {
426 case Vg_UserMsg: ch = '='; break;
427 case Vg_DebugMsg: ch = '-'; break;
428 case Vg_DebugExtraMsg: ch = '+'; break;
429 case Vg_ClientMsg: ch = '*'; break;
430 default: ch = '?'; break;
431 }
sewardj738856f2009-07-15 14:48:32 +0000432
njnb1cc5d62010-07-06 04:05:23 +0000433 b->buf[b->buf_used++] = ch;
434 b->buf[b->buf_used++] = ch;
435
436 if (VG_(clo_time_stamp)) {
437 VG_(memset)(tmp, 0, sizeof(tmp));
438 VG_(elapsed_wallclock_time)(tmp);
439 tmp[sizeof(tmp)-1] = 0;
440 for (i = 0; tmp[i]; i++)
441 b->buf[b->buf_used++] = tmp[i];
442 }
443
444 VG_(sprintf)(tmp, "%d", VG_(getpid)());
sewardj738856f2009-07-15 14:48:32 +0000445 tmp[sizeof(tmp)-1] = 0;
446 for (i = 0; tmp[i]; i++)
447 b->buf[b->buf_used++] = tmp[i];
njnb1cc5d62010-07-06 04:05:23 +0000448
449 b->buf[b->buf_used++] = ch;
450 b->buf[b->buf_used++] = ch;
451 b->buf[b->buf_used++] = ' ';
sewardj738856f2009-07-15 14:48:32 +0000452 }
453
sewardj738856f2009-07-15 14:48:32 +0000454 /* We can't possibly have stuffed 96 chars in merely as a result
455 of making the preamble (can we?) */
456 vg_assert(b->buf_used < sizeof(b->buf)-32);
457 }
458
459 b->buf[b->buf_used++] = c;
460 b->buf[b->buf_used] = 0;
461
462 if (b->buf_used >= sizeof(b->buf) - 128) {
463 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
464 b->buf_used = 0;
465 }
466
467 b->atLeft = c == '\n';
468}
469
470
njnc44a6c22005-06-03 13:21:18 +0000471UInt VG_(vmessage) ( VgMsgKind kind, const HChar* format, va_list vargs )
472{
sewardj738856f2009-07-15 14:48:32 +0000473 UInt ret;
njnc44a6c22005-06-03 13:21:18 +0000474
sewardj738856f2009-07-15 14:48:32 +0000475 /* Note (carefully) that the buf persists from call to call, unlike
476 with the other printf variants in earlier parts of this file. */
477 vmessage_buf_t* b = &vmessage_buf; /* shorthand for convenience */
478
479 /* We have to set this each call, so that the correct flavour
480 of preamble is emitted at each \n. */
481 b->kind = kind;
482
sewardj738856f2009-07-15 14:48:32 +0000483 ret = VG_(debugLog_vprintf) ( add_to__vmessage_buf,
484 b, format, vargs );
njnc44a6c22005-06-03 13:21:18 +0000485
sewardj738856f2009-07-15 14:48:32 +0000486 /* If the message finished exactly with a \n, then flush it at this
487 point. If not, assume more bits of the same line will turn up
488 in later messages, so don't bother to flush it right now. */
489
490 if (b->atLeft && b->buf_used > 0) {
491 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
492 b->buf_used = 0;
njnc44a6c22005-06-03 13:21:18 +0000493 }
494
sewardj738856f2009-07-15 14:48:32 +0000495 return ret;
njnc44a6c22005-06-03 13:21:18 +0000496}
497
barta0b6b2c2008-07-07 06:49:24 +0000498/* Send a simple single-part XML message. */
499UInt VG_(message_no_f_c) ( VgMsgKind kind, const HChar* format, ... )
500{
501 UInt count;
502 va_list vargs;
503 va_start(vargs,format);
504 count = VG_(vmessage) ( kind, format, vargs );
505 va_end(vargs);
506 return count;
507}
508
njnc44a6c22005-06-03 13:21:18 +0000509/* Send a simple single-part message. */
510UInt VG_(message) ( VgMsgKind kind, const HChar* format, ... )
511{
512 UInt count;
513 va_list vargs;
514 va_start(vargs,format);
515 count = VG_(vmessage) ( kind, format, vargs );
516 va_end(vargs);
517 return count;
518}
519
njnb1cc5d62010-07-06 04:05:23 +0000520static void revert_to_stderr ( void )
521{
522 VG_(log_output_sink).fd = 2; /* stderr */
523 VG_(log_output_sink).is_socket = False;
524}
525
sewardj738856f2009-07-15 14:48:32 +0000526/* VG_(message) variants with hardwired first argument. */
njnb1cc5d62010-07-06 04:05:23 +0000527
528UInt VG_(fmsg) ( const HChar* format, ... )
529{
530 UInt count;
531 va_list vargs;
532 va_start(vargs,format);
533 count = VG_(vmessage) ( Vg_FailMsg, format, vargs );
534 va_end(vargs);
535 return count;
536}
537
538void VG_(fmsg_bad_option) ( HChar* opt, const HChar* format, ... )
539{
540 va_list vargs;
541 va_start(vargs,format);
542 revert_to_stderr();
543 VG_(message) (Vg_FailMsg, "Bad option: %s\n", opt);
544 VG_(vmessage)(Vg_FailMsg, format, vargs );
545 VG_(message) (Vg_FailMsg, "Use --help for more information or consult the user manual.\n");
546 VG_(exit)(1);
547 va_end(vargs);
548}
549
sewardj738856f2009-07-15 14:48:32 +0000550UInt VG_(umsg) ( const HChar* format, ... )
551{
552 UInt count;
553 va_list vargs;
554 va_start(vargs,format);
555 count = VG_(vmessage) ( Vg_UserMsg, format, vargs );
556 va_end(vargs);
557 return count;
558}
559
560UInt VG_(dmsg) ( const HChar* format, ... )
561{
562 UInt count;
563 va_list vargs;
564 va_start(vargs,format);
565 count = VG_(vmessage) ( Vg_DebugMsg, format, vargs );
566 va_end(vargs);
567 return count;
568}
569
570UInt VG_(emsg) ( const HChar* format, ... )
571{
572 UInt count;
573 va_list vargs;
574 va_start(vargs,format);
575 count = VG_(vmessage) ( Vg_DebugExtraMsg, format, vargs );
576 va_end(vargs);
577 return count;
578}
579
580/* Flush any output that has accumulated in vmessage_buf as a
581 result of previous calls to VG_(message) et al. */
582void VG_(message_flush) ( void )
583{
584 vmessage_buf_t* b = &vmessage_buf;
585 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
586 b->buf_used = 0;
587}
588
njnb1cc5d62010-07-06 04:05:23 +0000589__attribute__((noreturn))
590void VG_(err_missing_prog) ( void )
591{
592 revert_to_stderr();
593 VG_(fmsg)("no program specified\n");
594 VG_(fmsg)("Use --help for more information.\n");
595 VG_(exit)(1);
596}
597
598__attribute__((noreturn))
599void VG_(err_config_error) ( Char* msg )
600{
601 revert_to_stderr();
602 VG_(fmsg)("Startup or configuration error:\n %s\n", msg);
603 VG_(fmsg)("Unable to start up properly. Giving up.\n");
604 VG_(exit)(1);
605}
606
sewardj738856f2009-07-15 14:48:32 +0000607
njnc44a6c22005-06-03 13:21:18 +0000608/*--------------------------------------------------------------------*/
609/*--- end ---*/
610/*--------------------------------------------------------------------*/
611