blob: 3657da4b5212b409037906e625bff4ec8b194f03 [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
sewardjec062e82011-10-23 07:32:08 +000010 Copyright (C) 2000-2011 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
170/* --------- sprintf --------- */
171
172/* If we had an explicit buf structure here, it would contain only one
173 field, indicating where the next char is to go. So use p directly
174 for that, rather than having it be a pointer to a structure. */
175
176static void add_to__sprintf_buf ( HChar c, void *p )
177{
178 HChar** b = p;
179 *(*b)++ = c;
njnc44a6c22005-06-03 13:21:18 +0000180}
181
182UInt VG_(vsprintf) ( Char* buf, const HChar *format, va_list vargs )
183{
184 Int ret;
sewardj738856f2009-07-15 14:48:32 +0000185 HChar* sprintf_ptr = buf;
njnc44a6c22005-06-03 13:21:18 +0000186
187 ret = VG_(debugLog_vprintf)
sewardj738856f2009-07-15 14:48:32 +0000188 ( add_to__sprintf_buf, &sprintf_ptr, format, vargs );
189 add_to__sprintf_buf('\0', &sprintf_ptr);
njnc44a6c22005-06-03 13:21:18 +0000190
191 vg_assert(VG_(strlen)(buf) == ret);
192
193 return ret;
194}
195
196UInt VG_(sprintf) ( Char* buf, const HChar *format, ... )
197{
198 UInt ret;
199 va_list vargs;
njnc44a6c22005-06-03 13:21:18 +0000200 va_start(vargs,format);
201 ret = VG_(vsprintf)(buf, format, vargs);
202 va_end(vargs);
njnc44a6c22005-06-03 13:21:18 +0000203 return ret;
204}
205
sewardj45f4e7c2005-09-27 19:20:21 +0000206
sewardj738856f2009-07-15 14:48:32 +0000207/* --------- snprintf --------- */
208
sewardj45f4e7c2005-09-27 19:20:21 +0000209typedef
210 struct {
211 HChar* buf;
212 Int buf_size;
213 Int buf_used;
214 }
sewardj738856f2009-07-15 14:48:32 +0000215 snprintf_buf_t;
sewardj45f4e7c2005-09-27 19:20:21 +0000216
sewardj738856f2009-07-15 14:48:32 +0000217static void add_to__snprintf_buf ( HChar c, void* p )
sewardj45f4e7c2005-09-27 19:20:21 +0000218{
sewardj738856f2009-07-15 14:48:32 +0000219 snprintf_buf_t* b = p;
sewardj45f4e7c2005-09-27 19:20:21 +0000220 if (b->buf_size > 0 && b->buf_used < b->buf_size) {
221 b->buf[b->buf_used++] = c;
222 if (b->buf_used < b->buf_size)
223 b->buf[b->buf_used] = 0;
sewardj03e2bb82006-12-24 03:02:18 +0000224 else
225 b->buf[b->buf_size-1] = 0; /* pre: b->buf_size > 0 */
sewardj45f4e7c2005-09-27 19:20:21 +0000226 }
227}
228
229UInt VG_(vsnprintf) ( Char* buf, Int size, const HChar *format, va_list vargs )
230{
sewardj738856f2009-07-15 14:48:32 +0000231 snprintf_buf_t b;
sewardj45f4e7c2005-09-27 19:20:21 +0000232 b.buf = buf;
233 b.buf_size = size < 0 ? 0 : size;
234 b.buf_used = 0;
235
sewardjc7ffc942011-03-28 16:26:42 +0000236 (void) VG_(debugLog_vprintf)
237 ( add_to__snprintf_buf, &b, format, vargs );
sewardj45f4e7c2005-09-27 19:20:21 +0000238
239 return b.buf_used;
240}
241
242UInt VG_(snprintf) ( Char* buf, Int size, const HChar *format, ... )
243{
244 UInt ret;
245 va_list vargs;
sewardj45f4e7c2005-09-27 19:20:21 +0000246 va_start(vargs,format);
247 ret = VG_(vsnprintf)(buf, size, format, vargs);
248 va_end(vargs);
sewardj45f4e7c2005-09-27 19:20:21 +0000249 return ret;
250}
251
252
sewardj738856f2009-07-15 14:48:32 +0000253/* --------- vcbprintf --------- */
254
255void VG_(vcbprintf)( void(*char_sink)(HChar, void* opaque),
256 void* opaque,
257 const HChar* format, va_list vargs )
258{
259 (void) VG_(debugLog_vprintf)
260 ( char_sink, opaque, format, vargs );
261}
262
263
njnc44a6c22005-06-03 13:21:18 +0000264/* ---------------------------------------------------------------------
njn856c54e2005-06-26 18:43:40 +0000265 percentify()
266 ------------------------------------------------------------------ */
267
njn7a5915e2005-07-17 16:12:59 +0000268// Percentify n/m with d decimal places. Includes the '%' symbol at the end.
njn5eaff2f2005-09-25 19:11:45 +0000269// Right justifies in 'buf'.
270void VG_(percentify)(ULong n, ULong m, UInt d, Int n_buf, char buf[])
njn856c54e2005-06-26 18:43:40 +0000271{
272 Int i, len, space;
njn641e6162005-07-17 16:16:41 +0000273 ULong p1;
njn5eaff2f2005-09-25 19:11:45 +0000274 Char fmt[32];
njn856c54e2005-06-26 18:43:40 +0000275
njn641e6162005-07-17 16:16:41 +0000276 if (m == 0) {
njn5eaff2f2005-09-25 19:11:45 +0000277 // Have to generate the format string in order to be flexible about
278 // the width of the field.
njn8a7b41b2007-09-23 00:51:24 +0000279 VG_(sprintf)(fmt, "%%-%ds", n_buf);
njn5eaff2f2005-09-25 19:11:45 +0000280 // fmt is now "%<n_buf>s" where <d> is 1,2,3...
281 VG_(sprintf)(buf, fmt, "--%");
njn641e6162005-07-17 16:16:41 +0000282 return;
283 }
284
285 p1 = (100*n) / m;
njn856c54e2005-06-26 18:43:40 +0000286
287 if (d == 0) {
288 VG_(sprintf)(buf, "%lld%%", p1);
289 } else {
290 ULong p2;
291 UInt ex;
njn856c54e2005-06-26 18:43:40 +0000292 switch (d) {
293 case 1: ex = 10; break;
294 case 2: ex = 100; break;
295 case 3: ex = 1000; break;
296 default: VG_(tool_panic)("Currently can only handle 3 decimal places");
297 }
298 p2 = ((100*n*ex) / m) % ex;
299 // Have to generate the format string in order to be flexible about
300 // the width of the post-decimal-point part.
301 VG_(sprintf)(fmt, "%%lld.%%0%dlld%%%%", d);
302 // fmt is now "%lld.%0<d>lld%%" where <d> is 1,2,3...
303 VG_(sprintf)(buf, fmt, p1, p2);
304 }
305
306 len = VG_(strlen)(buf);
307 space = n_buf - len;
308 if (space < 0) space = 0; /* Allow for v. small field_width */
309 i = len;
310
311 /* Right justify in field */
312 for ( ; i >= 0; i--) buf[i + space] = buf[i];
313 for (i = 0; i < space; i++) buf[i] = ' ';
314}
315
sewardja11553a2005-07-19 12:17:05 +0000316
317/* ---------------------------------------------------------------------
sewardj592ae092005-11-08 19:01:44 +0000318 elapsed_wallclock_time()
sewardja11553a2005-07-19 12:17:05 +0000319 ------------------------------------------------------------------ */
320
sewardj592ae092005-11-08 19:01:44 +0000321/* Get the elapsed wallclock time since startup into buf, which must
322 16 chars long. This is unchecked. It also relies on the
323 millisecond timer having been set to zero by an initial read in
324 m_main during startup. */
sewardja11553a2005-07-19 12:17:05 +0000325
sewardj592ae092005-11-08 19:01:44 +0000326void VG_(elapsed_wallclock_time) ( /*OUT*/HChar* buf )
sewardja11553a2005-07-19 12:17:05 +0000327{
sewardj592ae092005-11-08 19:01:44 +0000328 UInt t, ms, s, mins, hours, days;
329
330 t = VG_(read_millisecond_timer)(); /* milliseconds */
331
332 ms = t % 1000;
333 t /= 1000; /* now in seconds */
334
335 s = t % 60;
336 t /= 60; /* now in minutes */
337
338 mins = t % 60;
339 t /= 60; /* now in hours */
340
341 hours = t % 24;
342 t /= 24; /* now in days */
343
344 days = t;
345
njn82baca72009-07-24 05:35:49 +0000346 VG_(sprintf)(buf, "%02u:%02u:%02u:%02u.%03u ", days, hours, mins, s, ms);
sewardja11553a2005-07-19 12:17:05 +0000347}
348
349
njn856c54e2005-06-26 18:43:40 +0000350/* ---------------------------------------------------------------------
njnc44a6c22005-06-03 13:21:18 +0000351 message()
352 ------------------------------------------------------------------ */
353
sewardj738856f2009-07-15 14:48:32 +0000354/* A buffer for accumulating VG_(message) style output. This is
355 pretty much the same as VG_(printf)'s scheme, with two differences:
356
357 * The message buffer persists between calls, so that multiple
358 calls to VG_(message) can build up output.
359
360 * Whenever the first character on a line is emitted, the
361 ==PID== style preamble is stuffed in before it.
362*/
363typedef
364 struct {
365 HChar buf[512+128];
366 Int buf_used;
367 Bool atLeft; /* notionally, is the next char position at the
368 leftmost column? */
369 /* Current message kind - changes from call to call */
370 VgMsgKind kind;
sewardj738856f2009-07-15 14:48:32 +0000371 /* destination */
372 OutputSink* sink;
373 }
374 vmessage_buf_t;
375
376static vmessage_buf_t vmessage_buf
sewardj8ddb93a2010-02-15 10:07:05 +0000377 = { "", 0, True, Vg_UserMsg, &VG_(log_output_sink) };
sewardj738856f2009-07-15 14:48:32 +0000378
379
380// Adds a single char to the buffer. We aim to have at least 128
381// bytes free in the buffer, so that it's always possible to emit
382// the preamble into the buffer if c happens to be the character
383// following a \n. When the buffer gets too full, we write its
384// contents to the logging sink.
385static void add_to__vmessage_buf ( HChar c, void *p )
386{
387 HChar tmp[64];
388 vmessage_buf_t* b = (vmessage_buf_t*)p;
389
390 vg_assert(b->buf_used >= 0 && b->buf_used < sizeof(b->buf)-128);
391
392 if (UNLIKELY(b->atLeft)) {
393 // insert preamble
394 HChar ch;
395 Int i, depth;
396
sewardj738856f2009-07-15 14:48:32 +0000397 // Print one '>' in front of the messages for each level of
398 // self-hosting being performed.
philippe72faf102012-03-11 22:24:03 +0000399 // Do not print such '>' if sim hint "no-inner-prefix" given
400 // (useful to run regression tests in an outer/inner setup
401 // and avoid the diff failing due to these unexpected '>').
sewardj738856f2009-07-15 14:48:32 +0000402 depth = RUNNING_ON_VALGRIND;
philippe72faf102012-03-11 22:24:03 +0000403 if (depth > 0 && !VG_(strstr)(VG_(clo_sim_hints), "no-inner-prefix")) {
404 if (depth > 10)
405 depth = 10; // ?!?!
406 for (i = 0; i < depth; i++) {
407 b->buf[b->buf_used++] = '>';
408 }
sewardj738856f2009-07-15 14:48:32 +0000409 }
410
njnb1cc5d62010-07-06 04:05:23 +0000411 if (Vg_FailMsg == b->kind) {
412 // "valgrind: " prefix.
413 b->buf[b->buf_used++] = 'v';
414 b->buf[b->buf_used++] = 'a';
415 b->buf[b->buf_used++] = 'l';
416 b->buf[b->buf_used++] = 'g';
417 b->buf[b->buf_used++] = 'r';
418 b->buf[b->buf_used++] = 'i';
419 b->buf[b->buf_used++] = 'n';
420 b->buf[b->buf_used++] = 'd';
421 b->buf[b->buf_used++] = ':';
422 b->buf[b->buf_used++] = ' ';
423 } else {
424 switch (b->kind) {
425 case Vg_UserMsg: ch = '='; break;
426 case Vg_DebugMsg: ch = '-'; break;
njnb1cc5d62010-07-06 04:05:23 +0000427 case Vg_ClientMsg: ch = '*'; break;
428 default: ch = '?'; break;
429 }
sewardj738856f2009-07-15 14:48:32 +0000430
njnb1cc5d62010-07-06 04:05:23 +0000431 b->buf[b->buf_used++] = ch;
432 b->buf[b->buf_used++] = ch;
433
434 if (VG_(clo_time_stamp)) {
435 VG_(memset)(tmp, 0, sizeof(tmp));
436 VG_(elapsed_wallclock_time)(tmp);
437 tmp[sizeof(tmp)-1] = 0;
438 for (i = 0; tmp[i]; i++)
439 b->buf[b->buf_used++] = tmp[i];
440 }
441
442 VG_(sprintf)(tmp, "%d", VG_(getpid)());
sewardj738856f2009-07-15 14:48:32 +0000443 tmp[sizeof(tmp)-1] = 0;
444 for (i = 0; tmp[i]; i++)
445 b->buf[b->buf_used++] = tmp[i];
njnb1cc5d62010-07-06 04:05:23 +0000446
447 b->buf[b->buf_used++] = ch;
448 b->buf[b->buf_used++] = ch;
449 b->buf[b->buf_used++] = ' ';
sewardj738856f2009-07-15 14:48:32 +0000450 }
451
sewardj738856f2009-07-15 14:48:32 +0000452 /* We can't possibly have stuffed 96 chars in merely as a result
453 of making the preamble (can we?) */
454 vg_assert(b->buf_used < sizeof(b->buf)-32);
455 }
456
457 b->buf[b->buf_used++] = c;
458 b->buf[b->buf_used] = 0;
459
460 if (b->buf_used >= sizeof(b->buf) - 128) {
461 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
462 b->buf_used = 0;
463 }
464
465 b->atLeft = c == '\n';
466}
467
468
njnc44a6c22005-06-03 13:21:18 +0000469UInt VG_(vmessage) ( VgMsgKind kind, const HChar* format, va_list vargs )
470{
sewardj738856f2009-07-15 14:48:32 +0000471 UInt ret;
njnc44a6c22005-06-03 13:21:18 +0000472
sewardj738856f2009-07-15 14:48:32 +0000473 /* Note (carefully) that the buf persists from call to call, unlike
474 with the other printf variants in earlier parts of this file. */
475 vmessage_buf_t* b = &vmessage_buf; /* shorthand for convenience */
476
477 /* We have to set this each call, so that the correct flavour
478 of preamble is emitted at each \n. */
479 b->kind = kind;
480
sewardj738856f2009-07-15 14:48:32 +0000481 ret = VG_(debugLog_vprintf) ( add_to__vmessage_buf,
482 b, format, vargs );
njnc44a6c22005-06-03 13:21:18 +0000483
sewardj738856f2009-07-15 14:48:32 +0000484 /* If the message finished exactly with a \n, then flush it at this
485 point. If not, assume more bits of the same line will turn up
486 in later messages, so don't bother to flush it right now. */
487
488 if (b->atLeft && b->buf_used > 0) {
489 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
490 b->buf_used = 0;
njnc44a6c22005-06-03 13:21:18 +0000491 }
492
sewardj738856f2009-07-15 14:48:32 +0000493 return ret;
njnc44a6c22005-06-03 13:21:18 +0000494}
495
njnc44a6c22005-06-03 13:21:18 +0000496/* Send a simple single-part message. */
497UInt VG_(message) ( VgMsgKind kind, const HChar* format, ... )
498{
499 UInt count;
500 va_list vargs;
501 va_start(vargs,format);
502 count = VG_(vmessage) ( kind, format, vargs );
503 va_end(vargs);
504 return count;
505}
506
njnb1cc5d62010-07-06 04:05:23 +0000507static void revert_to_stderr ( void )
508{
509 VG_(log_output_sink).fd = 2; /* stderr */
510 VG_(log_output_sink).is_socket = False;
511}
512
sewardj738856f2009-07-15 14:48:32 +0000513/* VG_(message) variants with hardwired first argument. */
njnb1cc5d62010-07-06 04:05:23 +0000514
515UInt VG_(fmsg) ( const HChar* format, ... )
516{
517 UInt count;
518 va_list vargs;
519 va_start(vargs,format);
520 count = VG_(vmessage) ( Vg_FailMsg, format, vargs );
521 va_end(vargs);
522 return count;
523}
524
525void VG_(fmsg_bad_option) ( HChar* opt, const HChar* format, ... )
526{
527 va_list vargs;
528 va_start(vargs,format);
529 revert_to_stderr();
530 VG_(message) (Vg_FailMsg, "Bad option: %s\n", opt);
531 VG_(vmessage)(Vg_FailMsg, format, vargs );
532 VG_(message) (Vg_FailMsg, "Use --help for more information or consult the user manual.\n");
533 VG_(exit)(1);
534 va_end(vargs);
535}
536
sewardj738856f2009-07-15 14:48:32 +0000537UInt VG_(umsg) ( const HChar* format, ... )
538{
539 UInt count;
540 va_list vargs;
541 va_start(vargs,format);
542 count = VG_(vmessage) ( Vg_UserMsg, format, vargs );
543 va_end(vargs);
544 return count;
545}
546
547UInt VG_(dmsg) ( const HChar* format, ... )
548{
549 UInt count;
550 va_list vargs;
551 va_start(vargs,format);
552 count = VG_(vmessage) ( Vg_DebugMsg, format, vargs );
553 va_end(vargs);
554 return count;
555}
556
sewardj738856f2009-07-15 14:48:32 +0000557/* Flush any output that has accumulated in vmessage_buf as a
558 result of previous calls to VG_(message) et al. */
559void VG_(message_flush) ( void )
560{
561 vmessage_buf_t* b = &vmessage_buf;
562 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
563 b->buf_used = 0;
564}
565
njnb1cc5d62010-07-06 04:05:23 +0000566__attribute__((noreturn))
567void VG_(err_missing_prog) ( void )
568{
569 revert_to_stderr();
570 VG_(fmsg)("no program specified\n");
571 VG_(fmsg)("Use --help for more information.\n");
572 VG_(exit)(1);
573}
574
575__attribute__((noreturn))
florian1763e812011-07-12 19:07:05 +0000576void VG_(err_config_error) ( Char* format, ... )
njnb1cc5d62010-07-06 04:05:23 +0000577{
florian1763e812011-07-12 19:07:05 +0000578 va_list vargs;
579 va_start(vargs,format);
njnb1cc5d62010-07-06 04:05:23 +0000580 revert_to_stderr();
florian1763e812011-07-12 19:07:05 +0000581 VG_(message) (Vg_FailMsg, "Startup or configuration error:\n ");
582 VG_(vmessage)(Vg_FailMsg, format, vargs );
583 VG_(message) (Vg_FailMsg, "Unable to start up properly. Giving up.\n");
njnb1cc5d62010-07-06 04:05:23 +0000584 VG_(exit)(1);
florian1763e812011-07-12 19:07:05 +0000585 va_end(vargs);
njnb1cc5d62010-07-06 04:05:23 +0000586}
587
sewardj738856f2009-07-15 14:48:32 +0000588
njnc44a6c22005-06-03 13:21:18 +0000589/*--------------------------------------------------------------------*/
590/*--- end ---*/
591/*--------------------------------------------------------------------*/
592