blob: d4e3bee967fb6cb93043b93e092a15b3434e83b4 [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
sewardj03f8d3f2012-08-05 15:46:46 +000010 Copyright (C) 2000-2012 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"
philippe0447bbd2012-10-17 21:32:03 +000034#include "pub_tool_gdbserver.h" // VG_(gdb_printf)
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
floriandbb35842012-10-27 18:39:11 +000060void send_bytes_to_logging_sink ( OutputSink* sink, const HChar* 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
floriandbb35842012-10-27 18:39:11 +0000182UInt VG_(vsprintf) ( HChar* buf, const HChar *format, va_list vargs )
njnc44a6c22005-06-03 13:21:18 +0000183{
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
floriandbb35842012-10-27 18:39:11 +0000196UInt VG_(sprintf) ( HChar* buf, const HChar *format, ... )
njnc44a6c22005-06-03 13:21:18 +0000197{
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
floriandbb35842012-10-27 18:39:11 +0000229UInt VG_(vsnprintf) ( HChar* buf, Int size, const HChar *format, va_list vargs )
sewardj45f4e7c2005-09-27 19:20:21 +0000230{
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;
philippe3a00f522013-02-26 21:54:28 +0000235 if (b.buf_size > 0)
236 b.buf[0] = 0; // ensure to null terminate buf if empty format
sewardjc7ffc942011-03-28 16:26:42 +0000237 (void) VG_(debugLog_vprintf)
238 ( add_to__snprintf_buf, &b, format, vargs );
sewardj45f4e7c2005-09-27 19:20:21 +0000239
240 return b.buf_used;
241}
242
floriandbb35842012-10-27 18:39:11 +0000243UInt VG_(snprintf) ( HChar* buf, Int size, const HChar *format, ... )
sewardj45f4e7c2005-09-27 19:20:21 +0000244{
245 UInt ret;
246 va_list vargs;
sewardj45f4e7c2005-09-27 19:20:21 +0000247 va_start(vargs,format);
248 ret = VG_(vsnprintf)(buf, size, format, vargs);
249 va_end(vargs);
sewardj45f4e7c2005-09-27 19:20:21 +0000250 return ret;
251}
252
253
sewardj738856f2009-07-15 14:48:32 +0000254/* --------- vcbprintf --------- */
255
256void VG_(vcbprintf)( void(*char_sink)(HChar, void* opaque),
257 void* opaque,
258 const HChar* format, va_list vargs )
259{
260 (void) VG_(debugLog_vprintf)
261 ( char_sink, opaque, format, vargs );
262}
263
264
njnc44a6c22005-06-03 13:21:18 +0000265/* ---------------------------------------------------------------------
njn856c54e2005-06-26 18:43:40 +0000266 percentify()
267 ------------------------------------------------------------------ */
268
njn7a5915e2005-07-17 16:12:59 +0000269// Percentify n/m with d decimal places. Includes the '%' symbol at the end.
njn5eaff2f2005-09-25 19:11:45 +0000270// Right justifies in 'buf'.
floriandbb35842012-10-27 18:39:11 +0000271void VG_(percentify)(ULong n, ULong m, UInt d, Int n_buf, HChar buf[])
njn856c54e2005-06-26 18:43:40 +0000272{
273 Int i, len, space;
njn641e6162005-07-17 16:16:41 +0000274 ULong p1;
floriandbb35842012-10-27 18:39:11 +0000275 HChar fmt[32];
njn856c54e2005-06-26 18:43:40 +0000276
njn641e6162005-07-17 16:16:41 +0000277 if (m == 0) {
njn5eaff2f2005-09-25 19:11:45 +0000278 // Have to generate the format string in order to be flexible about
279 // the width of the field.
njn8a7b41b2007-09-23 00:51:24 +0000280 VG_(sprintf)(fmt, "%%-%ds", n_buf);
njn5eaff2f2005-09-25 19:11:45 +0000281 // fmt is now "%<n_buf>s" where <d> is 1,2,3...
282 VG_(sprintf)(buf, fmt, "--%");
njn641e6162005-07-17 16:16:41 +0000283 return;
284 }
285
286 p1 = (100*n) / m;
njn856c54e2005-06-26 18:43:40 +0000287
288 if (d == 0) {
289 VG_(sprintf)(buf, "%lld%%", p1);
290 } else {
291 ULong p2;
292 UInt ex;
njn856c54e2005-06-26 18:43:40 +0000293 switch (d) {
294 case 1: ex = 10; break;
295 case 2: ex = 100; break;
296 case 3: ex = 1000; break;
297 default: VG_(tool_panic)("Currently can only handle 3 decimal places");
298 }
299 p2 = ((100*n*ex) / m) % ex;
300 // Have to generate the format string in order to be flexible about
301 // the width of the post-decimal-point part.
302 VG_(sprintf)(fmt, "%%lld.%%0%dlld%%%%", d);
303 // fmt is now "%lld.%0<d>lld%%" where <d> is 1,2,3...
304 VG_(sprintf)(buf, fmt, p1, p2);
305 }
306
307 len = VG_(strlen)(buf);
308 space = n_buf - len;
309 if (space < 0) space = 0; /* Allow for v. small field_width */
310 i = len;
311
312 /* Right justify in field */
313 for ( ; i >= 0; i--) buf[i + space] = buf[i];
314 for (i = 0; i < space; i++) buf[i] = ' ';
315}
316
sewardja11553a2005-07-19 12:17:05 +0000317
318/* ---------------------------------------------------------------------
sewardj592ae092005-11-08 19:01:44 +0000319 elapsed_wallclock_time()
sewardja11553a2005-07-19 12:17:05 +0000320 ------------------------------------------------------------------ */
321
sewardj592ae092005-11-08 19:01:44 +0000322/* Get the elapsed wallclock time since startup into buf, which must
323 16 chars long. This is unchecked. It also relies on the
324 millisecond timer having been set to zero by an initial read in
325 m_main during startup. */
sewardja11553a2005-07-19 12:17:05 +0000326
sewardj592ae092005-11-08 19:01:44 +0000327void VG_(elapsed_wallclock_time) ( /*OUT*/HChar* buf )
sewardja11553a2005-07-19 12:17:05 +0000328{
sewardj592ae092005-11-08 19:01:44 +0000329 UInt t, ms, s, mins, hours, days;
330
331 t = VG_(read_millisecond_timer)(); /* milliseconds */
332
333 ms = t % 1000;
334 t /= 1000; /* now in seconds */
335
336 s = t % 60;
337 t /= 60; /* now in minutes */
338
339 mins = t % 60;
340 t /= 60; /* now in hours */
341
342 hours = t % 24;
343 t /= 24; /* now in days */
344
345 days = t;
346
njn82baca72009-07-24 05:35:49 +0000347 VG_(sprintf)(buf, "%02u:%02u:%02u:%02u.%03u ", days, hours, mins, s, ms);
sewardja11553a2005-07-19 12:17:05 +0000348}
349
350
njn856c54e2005-06-26 18:43:40 +0000351/* ---------------------------------------------------------------------
njnc44a6c22005-06-03 13:21:18 +0000352 message()
353 ------------------------------------------------------------------ */
354
sewardj738856f2009-07-15 14:48:32 +0000355/* A buffer for accumulating VG_(message) style output. This is
356 pretty much the same as VG_(printf)'s scheme, with two differences:
357
358 * The message buffer persists between calls, so that multiple
359 calls to VG_(message) can build up output.
360
361 * Whenever the first character on a line is emitted, the
362 ==PID== style preamble is stuffed in before it.
363*/
364typedef
365 struct {
366 HChar buf[512+128];
367 Int buf_used;
368 Bool atLeft; /* notionally, is the next char position at the
369 leftmost column? */
370 /* Current message kind - changes from call to call */
371 VgMsgKind kind;
sewardj738856f2009-07-15 14:48:32 +0000372 /* destination */
373 OutputSink* sink;
374 }
375 vmessage_buf_t;
376
377static vmessage_buf_t vmessage_buf
sewardj8ddb93a2010-02-15 10:07:05 +0000378 = { "", 0, True, Vg_UserMsg, &VG_(log_output_sink) };
sewardj738856f2009-07-15 14:48:32 +0000379
380
381// Adds a single char to the buffer. We aim to have at least 128
382// bytes free in the buffer, so that it's always possible to emit
383// the preamble into the buffer if c happens to be the character
384// following a \n. When the buffer gets too full, we write its
385// contents to the logging sink.
386static void add_to__vmessage_buf ( HChar c, void *p )
387{
388 HChar tmp[64];
389 vmessage_buf_t* b = (vmessage_buf_t*)p;
390
391 vg_assert(b->buf_used >= 0 && b->buf_used < sizeof(b->buf)-128);
392
393 if (UNLIKELY(b->atLeft)) {
394 // insert preamble
395 HChar ch;
396 Int i, depth;
397
sewardj738856f2009-07-15 14:48:32 +0000398 // Print one '>' in front of the messages for each level of
399 // self-hosting being performed.
philippe72faf102012-03-11 22:24:03 +0000400 // Do not print such '>' if sim hint "no-inner-prefix" given
401 // (useful to run regression tests in an outer/inner setup
402 // and avoid the diff failing due to these unexpected '>').
sewardj738856f2009-07-15 14:48:32 +0000403 depth = RUNNING_ON_VALGRIND;
philippe72faf102012-03-11 22:24:03 +0000404 if (depth > 0 && !VG_(strstr)(VG_(clo_sim_hints), "no-inner-prefix")) {
405 if (depth > 10)
406 depth = 10; // ?!?!
407 for (i = 0; i < depth; i++) {
408 b->buf[b->buf_used++] = '>';
409 }
sewardj738856f2009-07-15 14:48:32 +0000410 }
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;
njnb1cc5d62010-07-06 04:05:23 +0000428 case Vg_ClientMsg: ch = '*'; break;
429 default: ch = '?'; break;
430 }
sewardj738856f2009-07-15 14:48:32 +0000431
njnb1cc5d62010-07-06 04:05:23 +0000432 b->buf[b->buf_used++] = ch;
433 b->buf[b->buf_used++] = ch;
434
435 if (VG_(clo_time_stamp)) {
436 VG_(memset)(tmp, 0, sizeof(tmp));
437 VG_(elapsed_wallclock_time)(tmp);
438 tmp[sizeof(tmp)-1] = 0;
439 for (i = 0; tmp[i]; i++)
440 b->buf[b->buf_used++] = tmp[i];
441 }
442
443 VG_(sprintf)(tmp, "%d", VG_(getpid)());
sewardj738856f2009-07-15 14:48:32 +0000444 tmp[sizeof(tmp)-1] = 0;
445 for (i = 0; tmp[i]; i++)
446 b->buf[b->buf_used++] = tmp[i];
njnb1cc5d62010-07-06 04:05:23 +0000447
448 b->buf[b->buf_used++] = ch;
449 b->buf[b->buf_used++] = ch;
450 b->buf[b->buf_used++] = ' ';
sewardj738856f2009-07-15 14:48:32 +0000451 }
452
sewardj738856f2009-07-15 14:48:32 +0000453 /* We can't possibly have stuffed 96 chars in merely as a result
454 of making the preamble (can we?) */
455 vg_assert(b->buf_used < sizeof(b->buf)-32);
456 }
457
458 b->buf[b->buf_used++] = c;
459 b->buf[b->buf_used] = 0;
460
461 if (b->buf_used >= sizeof(b->buf) - 128) {
462 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
463 b->buf_used = 0;
464 }
465
466 b->atLeft = c == '\n';
467}
468
469
njnc44a6c22005-06-03 13:21:18 +0000470UInt VG_(vmessage) ( VgMsgKind kind, const HChar* format, va_list vargs )
471{
sewardj738856f2009-07-15 14:48:32 +0000472 UInt ret;
njnc44a6c22005-06-03 13:21:18 +0000473
sewardj738856f2009-07-15 14:48:32 +0000474 /* Note (carefully) that the buf persists from call to call, unlike
475 with the other printf variants in earlier parts of this file. */
476 vmessage_buf_t* b = &vmessage_buf; /* shorthand for convenience */
477
478 /* We have to set this each call, so that the correct flavour
479 of preamble is emitted at each \n. */
480 b->kind = kind;
481
sewardj738856f2009-07-15 14:48:32 +0000482 ret = VG_(debugLog_vprintf) ( add_to__vmessage_buf,
483 b, format, vargs );
njnc44a6c22005-06-03 13:21:18 +0000484
sewardj738856f2009-07-15 14:48:32 +0000485 /* If the message finished exactly with a \n, then flush it at this
486 point. If not, assume more bits of the same line will turn up
487 in later messages, so don't bother to flush it right now. */
488
489 if (b->atLeft && b->buf_used > 0) {
490 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
491 b->buf_used = 0;
njnc44a6c22005-06-03 13:21:18 +0000492 }
493
sewardj738856f2009-07-15 14:48:32 +0000494 return ret;
njnc44a6c22005-06-03 13:21:18 +0000495}
496
njnc44a6c22005-06-03 13:21:18 +0000497/* Send a simple single-part message. */
498UInt VG_(message) ( VgMsgKind kind, const HChar* format, ... )
499{
500 UInt count;
501 va_list vargs;
502 va_start(vargs,format);
503 count = VG_(vmessage) ( kind, format, vargs );
504 va_end(vargs);
505 return count;
506}
507
njnb1cc5d62010-07-06 04:05:23 +0000508static void revert_to_stderr ( void )
509{
510 VG_(log_output_sink).fd = 2; /* stderr */
511 VG_(log_output_sink).is_socket = False;
512}
513
sewardj738856f2009-07-15 14:48:32 +0000514/* VG_(message) variants with hardwired first argument. */
njnb1cc5d62010-07-06 04:05:23 +0000515
516UInt VG_(fmsg) ( const HChar* format, ... )
517{
518 UInt count;
519 va_list vargs;
520 va_start(vargs,format);
521 count = VG_(vmessage) ( Vg_FailMsg, format, vargs );
522 va_end(vargs);
523 return count;
524}
525
florianbbd9a212012-10-14 00:16:28 +0000526void VG_(fmsg_bad_option) ( const HChar* opt, const HChar* format, ... )
njnb1cc5d62010-07-06 04:05:23 +0000527{
528 va_list vargs;
529 va_start(vargs,format);
530 revert_to_stderr();
531 VG_(message) (Vg_FailMsg, "Bad option: %s\n", opt);
532 VG_(vmessage)(Vg_FailMsg, format, vargs );
533 VG_(message) (Vg_FailMsg, "Use --help for more information or consult the user manual.\n");
534 VG_(exit)(1);
535 va_end(vargs);
536}
537
sewardj738856f2009-07-15 14:48:32 +0000538UInt VG_(umsg) ( const HChar* format, ... )
539{
540 UInt count;
541 va_list vargs;
542 va_start(vargs,format);
543 count = VG_(vmessage) ( Vg_UserMsg, format, vargs );
544 va_end(vargs);
545 return count;
546}
547
548UInt VG_(dmsg) ( const HChar* format, ... )
549{
550 UInt count;
551 va_list vargs;
552 va_start(vargs,format);
553 count = VG_(vmessage) ( Vg_DebugMsg, format, vargs );
554 va_end(vargs);
555 return count;
556}
557
sewardj738856f2009-07-15 14:48:32 +0000558/* Flush any output that has accumulated in vmessage_buf as a
559 result of previous calls to VG_(message) et al. */
560void VG_(message_flush) ( void )
561{
562 vmessage_buf_t* b = &vmessage_buf;
563 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
564 b->buf_used = 0;
565}
566
njnb1cc5d62010-07-06 04:05:23 +0000567__attribute__((noreturn))
568void VG_(err_missing_prog) ( void )
569{
570 revert_to_stderr();
571 VG_(fmsg)("no program specified\n");
572 VG_(fmsg)("Use --help for more information.\n");
573 VG_(exit)(1);
574}
575
576__attribute__((noreturn))
florianbbd9a212012-10-14 00:16:28 +0000577void VG_(err_config_error) ( const HChar* format, ... )
njnb1cc5d62010-07-06 04:05:23 +0000578{
florian1763e812011-07-12 19:07:05 +0000579 va_list vargs;
580 va_start(vargs,format);
njnb1cc5d62010-07-06 04:05:23 +0000581 revert_to_stderr();
florian1763e812011-07-12 19:07:05 +0000582 VG_(message) (Vg_FailMsg, "Startup or configuration error:\n ");
583 VG_(vmessage)(Vg_FailMsg, format, vargs );
584 VG_(message) (Vg_FailMsg, "Unable to start up properly. Giving up.\n");
njnb1cc5d62010-07-06 04:05:23 +0000585 VG_(exit)(1);
florian1763e812011-07-12 19:07:05 +0000586 va_end(vargs);
njnb1cc5d62010-07-06 04:05:23 +0000587}
588
sewardj738856f2009-07-15 14:48:32 +0000589
njnc44a6c22005-06-03 13:21:18 +0000590/*--------------------------------------------------------------------*/
591/*--- end ---*/
592/*--------------------------------------------------------------------*/
593