blob: fb2544d514384dbee1b28a5e0d9f36f46acd88aa [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"
sewardj3b290482011-05-06 21:02:55 +000034#include "pub_core_gdbserver.h"
njnc44a6c22005-06-03 13:21:18 +000035#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000036#include "pub_core_libcassert.h"
sewardj592ae092005-11-08 19:01:44 +000037#include "pub_core_libcfile.h" // VG_(write)(), VG_(write_socket)()
njnc44a6c22005-06-03 13:21:18 +000038#include "pub_core_libcprint.h"
sewardj592ae092005-11-08 19:01:44 +000039#include "pub_core_libcproc.h" // VG_(getpid)(), VG_(read_millisecond_timer()
njnc44a6c22005-06-03 13:21:18 +000040#include "pub_core_options.h"
njn24a6efb2005-06-20 03:36:51 +000041#include "valgrind.h" // For RUNNING_ON_VALGRIND
njnc44a6c22005-06-03 13:21:18 +000042
njnc44a6c22005-06-03 13:21:18 +000043
44/* ---------------------------------------------------------------------
45 Writing to file or a socket
46 ------------------------------------------------------------------ */
47
sewardj738856f2009-07-15 14:48:32 +000048/* The destination sinks for normal and XML output. These have their
49 initial values here; they are set to final values by
50 m_main.main_process_cmd_line_options(). See comment at the top of
sewardj3b290482011-05-06 21:02:55 +000051 that function for the associated logic.
52 After startup, the gdbserver monitor command might temporarily
53 set the fd of log_output_sink to -2 to indicate that output is
54 to be given to gdb rather than output to the startup fd */
sewardj738856f2009-07-15 14:48:32 +000055OutputSink VG_(log_output_sink) = { 2, False }; /* 2 = stderr */
56OutputSink VG_(xml_output_sink) = { -1, False }; /* disabled */
57
njnc44a6c22005-06-03 13:21:18 +000058/* Do the low-level send of a message to the logging sink. */
sewardj738856f2009-07-15 14:48:32 +000059static
60void send_bytes_to_logging_sink ( OutputSink* sink, Char* msg, Int nbytes )
njnc44a6c22005-06-03 13:21:18 +000061{
sewardj738856f2009-07-15 14:48:32 +000062 if (sink->is_socket) {
63 Int rc = VG_(write_socket)( sink->fd, msg, nbytes );
64 if (rc == -1) {
65 // For example, the listener process died. Switch back to stderr.
66 sink->is_socket = False;
67 sink->fd = 2;
68 VG_(write)( sink->fd, msg, nbytes );
69 }
70 } else {
71 /* sink->fd could have been set to -1 in the various
sewardj6e31f802007-11-17 22:29:25 +000072 sys-wrappers for sys_fork, if --child-silent-after-fork=yes
73 is in effect. That is a signal that we should not produce
74 any more output. */
sewardj738856f2009-07-15 14:48:32 +000075 if (sink->fd >= 0)
76 VG_(write)( sink->fd, msg, nbytes );
sewardj3b290482011-05-06 21:02:55 +000077 else if (sink->fd == -2)
78 VG_(gdb_printf)("%s", msg);
njnc44a6c22005-06-03 13:21:18 +000079 }
80}
81
sewardj738856f2009-07-15 14:48:32 +000082
njnc44a6c22005-06-03 13:21:18 +000083/* ---------------------------------------------------------------------
84 printf() and friends
85 ------------------------------------------------------------------ */
86
sewardj738856f2009-07-15 14:48:32 +000087/* --------- printf --------- */
88
sewardj45f4e7c2005-09-27 19:20:21 +000089typedef
90 struct {
sewardj738856f2009-07-15 14:48:32 +000091 HChar buf[512];
92 Int buf_used;
93 OutputSink* sink;
sewardj45f4e7c2005-09-27 19:20:21 +000094 }
sewardj738856f2009-07-15 14:48:32 +000095 printf_buf_t;
bart1a0cb6a2008-04-14 16:35:32 +000096
njnc44a6c22005-06-03 13:21:18 +000097// Adds a single char to the buffer. When the buffer gets sufficiently
98// full, we write its contents to the logging sink.
sewardj738856f2009-07-15 14:48:32 +000099static void add_to__printf_buf ( HChar c, void *p )
njnc44a6c22005-06-03 13:21:18 +0000100{
sewardj738856f2009-07-15 14:48:32 +0000101 printf_buf_t *b = (printf_buf_t *)p;
njnc44a6c22005-06-03 13:21:18 +0000102
sewardj738856f2009-07-15 14:48:32 +0000103 if (b->buf_used > sizeof(b->buf) - 2 ) {
104 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
105 b->buf_used = 0;
njnc44a6c22005-06-03 13:21:18 +0000106 }
sewardj738856f2009-07-15 14:48:32 +0000107 b->buf[b->buf_used++] = c;
108 b->buf[b->buf_used] = 0;
109 tl_assert(b->buf_used < sizeof(b->buf));
110}
111
112static UInt vprintf_to_buf ( printf_buf_t* b,
113 const HChar *format, va_list vargs )
114{
115 UInt ret = 0;
sewardj3b290482011-05-06 21:02:55 +0000116 if (b->sink->fd >= 0 || b->sink->fd == -2) {
sewardj738856f2009-07-15 14:48:32 +0000117 ret = VG_(debugLog_vprintf)
118 ( add_to__printf_buf, b, format, vargs );
119 }
120 return ret;
121}
122
123static UInt vprintf_WRK ( OutputSink* sink,
124 const HChar *format, va_list vargs )
125{
126 printf_buf_t myprintf_buf
127 = { "", 0, sink };
128 UInt ret
129 = vprintf_to_buf(&myprintf_buf, format, vargs);
130 // Write out any chars left in the buffer.
131 if (myprintf_buf.buf_used > 0) {
132 send_bytes_to_logging_sink( myprintf_buf.sink,
133 myprintf_buf.buf,
134 myprintf_buf.buf_used );
135 }
136 return ret;
njnc44a6c22005-06-03 13:21:18 +0000137}
138
139UInt VG_(vprintf) ( const HChar *format, va_list vargs )
140{
sewardj738856f2009-07-15 14:48:32 +0000141 return vprintf_WRK( &VG_(log_output_sink), format, vargs );
njnc44a6c22005-06-03 13:21:18 +0000142}
143
144UInt VG_(printf) ( const HChar *format, ... )
145{
146 UInt ret;
147 va_list vargs;
njnc44a6c22005-06-03 13:21:18 +0000148 va_start(vargs, format);
149 ret = VG_(vprintf)(format, vargs);
150 va_end(vargs);
njnc44a6c22005-06-03 13:21:18 +0000151 return ret;
152}
153
sewardj738856f2009-07-15 14:48:32 +0000154UInt VG_(vprintf_xml) ( const HChar *format, va_list vargs )
155{
156 return vprintf_WRK( &VG_(xml_output_sink), format, vargs );
157}
158
159UInt VG_(printf_xml) ( const HChar *format, ... )
bart1a0cb6a2008-04-14 16:35:32 +0000160{
161 UInt ret;
162 va_list vargs;
bart1a0cb6a2008-04-14 16:35:32 +0000163 va_start(vargs, format);
sewardj738856f2009-07-15 14:48:32 +0000164 ret = VG_(vprintf_xml)(format, vargs);
bart1a0cb6a2008-04-14 16:35:32 +0000165 va_end(vargs);
bart1a0cb6a2008-04-14 16:35:32 +0000166 return ret;
167}
168
sewardj738856f2009-07-15 14:48:32 +0000169/* An exact clone of VG_(printf_xml), unfortunately. */
170UInt VG_(printf_xml_no_f_c) ( const HChar *format, ... )
njnc44a6c22005-06-03 13:21:18 +0000171{
sewardj738856f2009-07-15 14:48:32 +0000172 UInt ret;
173 va_list vargs;
174 va_start(vargs, format);
175 ret = VG_(vprintf_xml)(format, vargs);
176 va_end(vargs);
177 return ret;
178}
179
180
181/* --------- sprintf --------- */
182
183/* If we had an explicit buf structure here, it would contain only one
184 field, indicating where the next char is to go. So use p directly
185 for that, rather than having it be a pointer to a structure. */
186
187static void add_to__sprintf_buf ( HChar c, void *p )
188{
189 HChar** b = p;
190 *(*b)++ = c;
njnc44a6c22005-06-03 13:21:18 +0000191}
192
193UInt VG_(vsprintf) ( Char* buf, const HChar *format, va_list vargs )
194{
195 Int ret;
sewardj738856f2009-07-15 14:48:32 +0000196 HChar* sprintf_ptr = buf;
njnc44a6c22005-06-03 13:21:18 +0000197
198 ret = VG_(debugLog_vprintf)
sewardj738856f2009-07-15 14:48:32 +0000199 ( add_to__sprintf_buf, &sprintf_ptr, format, vargs );
200 add_to__sprintf_buf('\0', &sprintf_ptr);
njnc44a6c22005-06-03 13:21:18 +0000201
202 vg_assert(VG_(strlen)(buf) == ret);
203
204 return ret;
205}
206
207UInt VG_(sprintf) ( Char* buf, const HChar *format, ... )
208{
209 UInt ret;
210 va_list vargs;
njnc44a6c22005-06-03 13:21:18 +0000211 va_start(vargs,format);
212 ret = VG_(vsprintf)(buf, format, vargs);
213 va_end(vargs);
njnc44a6c22005-06-03 13:21:18 +0000214 return ret;
215}
216
sewardj45f4e7c2005-09-27 19:20:21 +0000217
sewardj738856f2009-07-15 14:48:32 +0000218/* --------- snprintf --------- */
219
sewardj45f4e7c2005-09-27 19:20:21 +0000220typedef
221 struct {
222 HChar* buf;
223 Int buf_size;
224 Int buf_used;
225 }
sewardj738856f2009-07-15 14:48:32 +0000226 snprintf_buf_t;
sewardj45f4e7c2005-09-27 19:20:21 +0000227
sewardj738856f2009-07-15 14:48:32 +0000228static void add_to__snprintf_buf ( HChar c, void* p )
sewardj45f4e7c2005-09-27 19:20:21 +0000229{
sewardj738856f2009-07-15 14:48:32 +0000230 snprintf_buf_t* b = p;
sewardj45f4e7c2005-09-27 19:20:21 +0000231 if (b->buf_size > 0 && b->buf_used < b->buf_size) {
232 b->buf[b->buf_used++] = c;
233 if (b->buf_used < b->buf_size)
234 b->buf[b->buf_used] = 0;
sewardj03e2bb82006-12-24 03:02:18 +0000235 else
236 b->buf[b->buf_size-1] = 0; /* pre: b->buf_size > 0 */
sewardj45f4e7c2005-09-27 19:20:21 +0000237 }
238}
239
240UInt VG_(vsnprintf) ( Char* buf, Int size, const HChar *format, va_list vargs )
241{
sewardj738856f2009-07-15 14:48:32 +0000242 snprintf_buf_t b;
sewardj45f4e7c2005-09-27 19:20:21 +0000243 b.buf = buf;
244 b.buf_size = size < 0 ? 0 : size;
245 b.buf_used = 0;
246
sewardjc7ffc942011-03-28 16:26:42 +0000247 (void) VG_(debugLog_vprintf)
248 ( add_to__snprintf_buf, &b, format, vargs );
sewardj45f4e7c2005-09-27 19:20:21 +0000249
250 return b.buf_used;
251}
252
253UInt VG_(snprintf) ( Char* buf, Int size, const HChar *format, ... )
254{
255 UInt ret;
256 va_list vargs;
sewardj45f4e7c2005-09-27 19:20:21 +0000257 va_start(vargs,format);
258 ret = VG_(vsnprintf)(buf, size, format, vargs);
259 va_end(vargs);
sewardj45f4e7c2005-09-27 19:20:21 +0000260 return ret;
261}
262
263
sewardj738856f2009-07-15 14:48:32 +0000264/* --------- vcbprintf --------- */
265
266void VG_(vcbprintf)( void(*char_sink)(HChar, void* opaque),
267 void* opaque,
268 const HChar* format, va_list vargs )
269{
270 (void) VG_(debugLog_vprintf)
271 ( char_sink, opaque, format, vargs );
272}
273
274
njnc44a6c22005-06-03 13:21:18 +0000275/* ---------------------------------------------------------------------
njn856c54e2005-06-26 18:43:40 +0000276 percentify()
277 ------------------------------------------------------------------ */
278
njn7a5915e2005-07-17 16:12:59 +0000279// Percentify n/m with d decimal places. Includes the '%' symbol at the end.
njn5eaff2f2005-09-25 19:11:45 +0000280// Right justifies in 'buf'.
281void VG_(percentify)(ULong n, ULong m, UInt d, Int n_buf, char buf[])
njn856c54e2005-06-26 18:43:40 +0000282{
283 Int i, len, space;
njn641e6162005-07-17 16:16:41 +0000284 ULong p1;
njn5eaff2f2005-09-25 19:11:45 +0000285 Char fmt[32];
njn856c54e2005-06-26 18:43:40 +0000286
njn641e6162005-07-17 16:16:41 +0000287 if (m == 0) {
njn5eaff2f2005-09-25 19:11:45 +0000288 // Have to generate the format string in order to be flexible about
289 // the width of the field.
njn8a7b41b2007-09-23 00:51:24 +0000290 VG_(sprintf)(fmt, "%%-%ds", n_buf);
njn5eaff2f2005-09-25 19:11:45 +0000291 // fmt is now "%<n_buf>s" where <d> is 1,2,3...
292 VG_(sprintf)(buf, fmt, "--%");
njn641e6162005-07-17 16:16:41 +0000293 return;
294 }
295
296 p1 = (100*n) / m;
njn856c54e2005-06-26 18:43:40 +0000297
298 if (d == 0) {
299 VG_(sprintf)(buf, "%lld%%", p1);
300 } else {
301 ULong p2;
302 UInt ex;
njn856c54e2005-06-26 18:43:40 +0000303 switch (d) {
304 case 1: ex = 10; break;
305 case 2: ex = 100; break;
306 case 3: ex = 1000; break;
307 default: VG_(tool_panic)("Currently can only handle 3 decimal places");
308 }
309 p2 = ((100*n*ex) / m) % ex;
310 // Have to generate the format string in order to be flexible about
311 // the width of the post-decimal-point part.
312 VG_(sprintf)(fmt, "%%lld.%%0%dlld%%%%", d);
313 // fmt is now "%lld.%0<d>lld%%" where <d> is 1,2,3...
314 VG_(sprintf)(buf, fmt, p1, p2);
315 }
316
317 len = VG_(strlen)(buf);
318 space = n_buf - len;
319 if (space < 0) space = 0; /* Allow for v. small field_width */
320 i = len;
321
322 /* Right justify in field */
323 for ( ; i >= 0; i--) buf[i + space] = buf[i];
324 for (i = 0; i < space; i++) buf[i] = ' ';
325}
326
sewardja11553a2005-07-19 12:17:05 +0000327
328/* ---------------------------------------------------------------------
sewardj592ae092005-11-08 19:01:44 +0000329 elapsed_wallclock_time()
sewardja11553a2005-07-19 12:17:05 +0000330 ------------------------------------------------------------------ */
331
sewardj592ae092005-11-08 19:01:44 +0000332/* Get the elapsed wallclock time since startup into buf, which must
333 16 chars long. This is unchecked. It also relies on the
334 millisecond timer having been set to zero by an initial read in
335 m_main during startup. */
sewardja11553a2005-07-19 12:17:05 +0000336
sewardj592ae092005-11-08 19:01:44 +0000337void VG_(elapsed_wallclock_time) ( /*OUT*/HChar* buf )
sewardja11553a2005-07-19 12:17:05 +0000338{
sewardj592ae092005-11-08 19:01:44 +0000339 UInt t, ms, s, mins, hours, days;
340
341 t = VG_(read_millisecond_timer)(); /* milliseconds */
342
343 ms = t % 1000;
344 t /= 1000; /* now in seconds */
345
346 s = t % 60;
347 t /= 60; /* now in minutes */
348
349 mins = t % 60;
350 t /= 60; /* now in hours */
351
352 hours = t % 24;
353 t /= 24; /* now in days */
354
355 days = t;
356
njn82baca72009-07-24 05:35:49 +0000357 VG_(sprintf)(buf, "%02u:%02u:%02u:%02u.%03u ", days, hours, mins, s, ms);
sewardja11553a2005-07-19 12:17:05 +0000358}
359
360
njn856c54e2005-06-26 18:43:40 +0000361/* ---------------------------------------------------------------------
njnc44a6c22005-06-03 13:21:18 +0000362 message()
363 ------------------------------------------------------------------ */
364
sewardj738856f2009-07-15 14:48:32 +0000365/* A buffer for accumulating VG_(message) style output. This is
366 pretty much the same as VG_(printf)'s scheme, with two differences:
367
368 * The message buffer persists between calls, so that multiple
369 calls to VG_(message) can build up output.
370
371 * Whenever the first character on a line is emitted, the
372 ==PID== style preamble is stuffed in before it.
373*/
374typedef
375 struct {
376 HChar buf[512+128];
377 Int buf_used;
378 Bool atLeft; /* notionally, is the next char position at the
379 leftmost column? */
380 /* Current message kind - changes from call to call */
381 VgMsgKind kind;
sewardj738856f2009-07-15 14:48:32 +0000382 /* destination */
383 OutputSink* sink;
384 }
385 vmessage_buf_t;
386
387static vmessage_buf_t vmessage_buf
sewardj8ddb93a2010-02-15 10:07:05 +0000388 = { "", 0, True, Vg_UserMsg, &VG_(log_output_sink) };
sewardj738856f2009-07-15 14:48:32 +0000389
390
391// Adds a single char to the buffer. We aim to have at least 128
392// bytes free in the buffer, so that it's always possible to emit
393// the preamble into the buffer if c happens to be the character
394// following a \n. When the buffer gets too full, we write its
395// contents to the logging sink.
396static void add_to__vmessage_buf ( HChar c, void *p )
397{
398 HChar tmp[64];
399 vmessage_buf_t* b = (vmessage_buf_t*)p;
400
401 vg_assert(b->buf_used >= 0 && b->buf_used < sizeof(b->buf)-128);
402
403 if (UNLIKELY(b->atLeft)) {
404 // insert preamble
405 HChar ch;
406 Int i, depth;
407
sewardj738856f2009-07-15 14:48:32 +0000408 // Print one '>' in front of the messages for each level of
409 // self-hosting being performed.
410 depth = RUNNING_ON_VALGRIND;
411 if (depth > 10)
412 depth = 10; // ?!?!
413 for (i = 0; i < depth; i++) {
414 b->buf[b->buf_used++] = '>';
415 }
416
njnb1cc5d62010-07-06 04:05:23 +0000417 if (Vg_FailMsg == b->kind) {
418 // "valgrind: " prefix.
419 b->buf[b->buf_used++] = 'v';
420 b->buf[b->buf_used++] = 'a';
421 b->buf[b->buf_used++] = 'l';
422 b->buf[b->buf_used++] = 'g';
423 b->buf[b->buf_used++] = 'r';
424 b->buf[b->buf_used++] = 'i';
425 b->buf[b->buf_used++] = 'n';
426 b->buf[b->buf_used++] = 'd';
427 b->buf[b->buf_used++] = ':';
428 b->buf[b->buf_used++] = ' ';
429 } else {
430 switch (b->kind) {
431 case Vg_UserMsg: ch = '='; break;
432 case Vg_DebugMsg: ch = '-'; break;
njnb1cc5d62010-07-06 04:05:23 +0000433 case Vg_ClientMsg: ch = '*'; break;
434 default: ch = '?'; break;
435 }
sewardj738856f2009-07-15 14:48:32 +0000436
njnb1cc5d62010-07-06 04:05:23 +0000437 b->buf[b->buf_used++] = ch;
438 b->buf[b->buf_used++] = ch;
439
440 if (VG_(clo_time_stamp)) {
441 VG_(memset)(tmp, 0, sizeof(tmp));
442 VG_(elapsed_wallclock_time)(tmp);
443 tmp[sizeof(tmp)-1] = 0;
444 for (i = 0; tmp[i]; i++)
445 b->buf[b->buf_used++] = tmp[i];
446 }
447
448 VG_(sprintf)(tmp, "%d", VG_(getpid)());
sewardj738856f2009-07-15 14:48:32 +0000449 tmp[sizeof(tmp)-1] = 0;
450 for (i = 0; tmp[i]; i++)
451 b->buf[b->buf_used++] = tmp[i];
njnb1cc5d62010-07-06 04:05:23 +0000452
453 b->buf[b->buf_used++] = ch;
454 b->buf[b->buf_used++] = ch;
455 b->buf[b->buf_used++] = ' ';
sewardj738856f2009-07-15 14:48:32 +0000456 }
457
sewardj738856f2009-07-15 14:48:32 +0000458 /* We can't possibly have stuffed 96 chars in merely as a result
459 of making the preamble (can we?) */
460 vg_assert(b->buf_used < sizeof(b->buf)-32);
461 }
462
463 b->buf[b->buf_used++] = c;
464 b->buf[b->buf_used] = 0;
465
466 if (b->buf_used >= sizeof(b->buf) - 128) {
467 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
468 b->buf_used = 0;
469 }
470
471 b->atLeft = c == '\n';
472}
473
474
njnc44a6c22005-06-03 13:21:18 +0000475UInt VG_(vmessage) ( VgMsgKind kind, const HChar* format, va_list vargs )
476{
sewardj738856f2009-07-15 14:48:32 +0000477 UInt ret;
njnc44a6c22005-06-03 13:21:18 +0000478
sewardj738856f2009-07-15 14:48:32 +0000479 /* Note (carefully) that the buf persists from call to call, unlike
480 with the other printf variants in earlier parts of this file. */
481 vmessage_buf_t* b = &vmessage_buf; /* shorthand for convenience */
482
483 /* We have to set this each call, so that the correct flavour
484 of preamble is emitted at each \n. */
485 b->kind = kind;
486
sewardj738856f2009-07-15 14:48:32 +0000487 ret = VG_(debugLog_vprintf) ( add_to__vmessage_buf,
488 b, format, vargs );
njnc44a6c22005-06-03 13:21:18 +0000489
sewardj738856f2009-07-15 14:48:32 +0000490 /* If the message finished exactly with a \n, then flush it at this
491 point. If not, assume more bits of the same line will turn up
492 in later messages, so don't bother to flush it right now. */
493
494 if (b->atLeft && b->buf_used > 0) {
495 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
496 b->buf_used = 0;
njnc44a6c22005-06-03 13:21:18 +0000497 }
498
sewardj738856f2009-07-15 14:48:32 +0000499 return ret;
njnc44a6c22005-06-03 13:21:18 +0000500}
501
barta0b6b2c2008-07-07 06:49:24 +0000502/* Send a simple single-part XML message. */
503UInt VG_(message_no_f_c) ( VgMsgKind kind, const HChar* format, ... )
504{
505 UInt count;
506 va_list vargs;
507 va_start(vargs,format);
508 count = VG_(vmessage) ( kind, format, vargs );
509 va_end(vargs);
510 return count;
511}
512
njnc44a6c22005-06-03 13:21:18 +0000513/* Send a simple single-part message. */
514UInt VG_(message) ( VgMsgKind kind, const HChar* format, ... )
515{
516 UInt count;
517 va_list vargs;
518 va_start(vargs,format);
519 count = VG_(vmessage) ( kind, format, vargs );
520 va_end(vargs);
521 return count;
522}
523
njnb1cc5d62010-07-06 04:05:23 +0000524static void revert_to_stderr ( void )
525{
526 VG_(log_output_sink).fd = 2; /* stderr */
527 VG_(log_output_sink).is_socket = False;
528}
529
sewardj738856f2009-07-15 14:48:32 +0000530/* VG_(message) variants with hardwired first argument. */
njnb1cc5d62010-07-06 04:05:23 +0000531
532UInt VG_(fmsg) ( const HChar* format, ... )
533{
534 UInt count;
535 va_list vargs;
536 va_start(vargs,format);
537 count = VG_(vmessage) ( Vg_FailMsg, format, vargs );
538 va_end(vargs);
539 return count;
540}
541
542void VG_(fmsg_bad_option) ( HChar* opt, const HChar* format, ... )
543{
544 va_list vargs;
545 va_start(vargs,format);
546 revert_to_stderr();
547 VG_(message) (Vg_FailMsg, "Bad option: %s\n", opt);
548 VG_(vmessage)(Vg_FailMsg, format, vargs );
549 VG_(message) (Vg_FailMsg, "Use --help for more information or consult the user manual.\n");
550 VG_(exit)(1);
551 va_end(vargs);
552}
553
sewardj738856f2009-07-15 14:48:32 +0000554UInt VG_(umsg) ( const HChar* format, ... )
555{
556 UInt count;
557 va_list vargs;
558 va_start(vargs,format);
559 count = VG_(vmessage) ( Vg_UserMsg, format, vargs );
560 va_end(vargs);
561 return count;
562}
563
564UInt VG_(dmsg) ( const HChar* format, ... )
565{
566 UInt count;
567 va_list vargs;
568 va_start(vargs,format);
569 count = VG_(vmessage) ( Vg_DebugMsg, format, vargs );
570 va_end(vargs);
571 return count;
572}
573
sewardj738856f2009-07-15 14:48:32 +0000574/* Flush any output that has accumulated in vmessage_buf as a
575 result of previous calls to VG_(message) et al. */
576void VG_(message_flush) ( void )
577{
578 vmessage_buf_t* b = &vmessage_buf;
579 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
580 b->buf_used = 0;
581}
582
njnb1cc5d62010-07-06 04:05:23 +0000583__attribute__((noreturn))
584void VG_(err_missing_prog) ( void )
585{
586 revert_to_stderr();
587 VG_(fmsg)("no program specified\n");
588 VG_(fmsg)("Use --help for more information.\n");
589 VG_(exit)(1);
590}
591
592__attribute__((noreturn))
593void VG_(err_config_error) ( Char* msg )
594{
595 revert_to_stderr();
596 VG_(fmsg)("Startup or configuration error:\n %s\n", msg);
597 VG_(fmsg)("Unable to start up properly. Giving up.\n");
598 VG_(exit)(1);
599}
600
sewardj738856f2009-07-15 14:48:32 +0000601
njnc44a6c22005-06-03 13:21:18 +0000602/*--------------------------------------------------------------------*/
603/*--- end ---*/
604/*--------------------------------------------------------------------*/
605