blob: ecffc83565fb9b8868e2e1e77df5a396a2ca6d1c [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"
florianc91f5842013-09-15 10:42:26 +000034#include "pub_core_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 );
philippe02ea4132013-09-04 21:42:43 +000077 else if (sink->fd == -2 && nbytes > 0)
78 /* send to gdb the provided data, which must be
79 a null terminated string with len >= 1 */
sewardj3b290482011-05-06 21:02:55 +000080 VG_(gdb_printf)("%s", msg);
njnc44a6c22005-06-03 13:21:18 +000081 }
82}
83
sewardj738856f2009-07-15 14:48:32 +000084
njnc44a6c22005-06-03 13:21:18 +000085/* ---------------------------------------------------------------------
86 printf() and friends
87 ------------------------------------------------------------------ */
88
sewardj738856f2009-07-15 14:48:32 +000089/* --------- printf --------- */
90
sewardj45f4e7c2005-09-27 19:20:21 +000091typedef
92 struct {
sewardj738856f2009-07-15 14:48:32 +000093 HChar buf[512];
94 Int buf_used;
95 OutputSink* sink;
sewardj45f4e7c2005-09-27 19:20:21 +000096 }
sewardj738856f2009-07-15 14:48:32 +000097 printf_buf_t;
bart1a0cb6a2008-04-14 16:35:32 +000098
njnc44a6c22005-06-03 13:21:18 +000099// Adds a single char to the buffer. When the buffer gets sufficiently
100// full, we write its contents to the logging sink.
sewardj738856f2009-07-15 14:48:32 +0000101static void add_to__printf_buf ( HChar c, void *p )
njnc44a6c22005-06-03 13:21:18 +0000102{
sewardj738856f2009-07-15 14:48:32 +0000103 printf_buf_t *b = (printf_buf_t *)p;
njnc44a6c22005-06-03 13:21:18 +0000104
sewardj738856f2009-07-15 14:48:32 +0000105 if (b->buf_used > sizeof(b->buf) - 2 ) {
106 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
107 b->buf_used = 0;
njnc44a6c22005-06-03 13:21:18 +0000108 }
sewardj738856f2009-07-15 14:48:32 +0000109 b->buf[b->buf_used++] = c;
110 b->buf[b->buf_used] = 0;
111 tl_assert(b->buf_used < sizeof(b->buf));
112}
113
114static UInt vprintf_to_buf ( printf_buf_t* b,
115 const HChar *format, va_list vargs )
116{
117 UInt ret = 0;
sewardj3b290482011-05-06 21:02:55 +0000118 if (b->sink->fd >= 0 || b->sink->fd == -2) {
sewardj738856f2009-07-15 14:48:32 +0000119 ret = VG_(debugLog_vprintf)
120 ( add_to__printf_buf, b, format, vargs );
121 }
122 return ret;
123}
124
125static UInt vprintf_WRK ( OutputSink* sink,
126 const HChar *format, va_list vargs )
127{
128 printf_buf_t myprintf_buf
129 = { "", 0, sink };
130 UInt ret
131 = vprintf_to_buf(&myprintf_buf, format, vargs);
132 // Write out any chars left in the buffer.
133 if (myprintf_buf.buf_used > 0) {
134 send_bytes_to_logging_sink( myprintf_buf.sink,
135 myprintf_buf.buf,
136 myprintf_buf.buf_used );
137 }
138 return ret;
njnc44a6c22005-06-03 13:21:18 +0000139}
140
141UInt VG_(vprintf) ( const HChar *format, va_list vargs )
142{
sewardj738856f2009-07-15 14:48:32 +0000143 return vprintf_WRK( &VG_(log_output_sink), format, vargs );
njnc44a6c22005-06-03 13:21:18 +0000144}
145
146UInt VG_(printf) ( const HChar *format, ... )
147{
148 UInt ret;
149 va_list vargs;
njnc44a6c22005-06-03 13:21:18 +0000150 va_start(vargs, format);
151 ret = VG_(vprintf)(format, vargs);
152 va_end(vargs);
njnc44a6c22005-06-03 13:21:18 +0000153 return ret;
154}
155
sewardj738856f2009-07-15 14:48:32 +0000156UInt VG_(vprintf_xml) ( const HChar *format, va_list vargs )
157{
158 return vprintf_WRK( &VG_(xml_output_sink), format, vargs );
159}
160
161UInt VG_(printf_xml) ( const HChar *format, ... )
bart1a0cb6a2008-04-14 16:35:32 +0000162{
163 UInt ret;
164 va_list vargs;
bart1a0cb6a2008-04-14 16:35:32 +0000165 va_start(vargs, format);
sewardj738856f2009-07-15 14:48:32 +0000166 ret = VG_(vprintf_xml)(format, vargs);
bart1a0cb6a2008-04-14 16:35:32 +0000167 va_end(vargs);
bart1a0cb6a2008-04-14 16:35:32 +0000168 return ret;
169}
170
sewardj738856f2009-07-15 14:48:32 +0000171
172/* --------- sprintf --------- */
173
174/* If we had an explicit buf structure here, it would contain only one
175 field, indicating where the next char is to go. So use p directly
176 for that, rather than having it be a pointer to a structure. */
177
178static void add_to__sprintf_buf ( HChar c, void *p )
179{
180 HChar** b = p;
181 *(*b)++ = c;
njnc44a6c22005-06-03 13:21:18 +0000182}
183
floriandbb35842012-10-27 18:39:11 +0000184UInt VG_(vsprintf) ( HChar* buf, const HChar *format, va_list vargs )
njnc44a6c22005-06-03 13:21:18 +0000185{
186 Int ret;
sewardj738856f2009-07-15 14:48:32 +0000187 HChar* sprintf_ptr = buf;
njnc44a6c22005-06-03 13:21:18 +0000188
189 ret = VG_(debugLog_vprintf)
sewardj738856f2009-07-15 14:48:32 +0000190 ( add_to__sprintf_buf, &sprintf_ptr, format, vargs );
191 add_to__sprintf_buf('\0', &sprintf_ptr);
njnc44a6c22005-06-03 13:21:18 +0000192
193 vg_assert(VG_(strlen)(buf) == ret);
194
195 return ret;
196}
197
floriandbb35842012-10-27 18:39:11 +0000198UInt VG_(sprintf) ( HChar* buf, const HChar *format, ... )
njnc44a6c22005-06-03 13:21:18 +0000199{
200 UInt ret;
201 va_list vargs;
njnc44a6c22005-06-03 13:21:18 +0000202 va_start(vargs,format);
203 ret = VG_(vsprintf)(buf, format, vargs);
204 va_end(vargs);
njnc44a6c22005-06-03 13:21:18 +0000205 return ret;
206}
207
sewardj45f4e7c2005-09-27 19:20:21 +0000208
sewardj738856f2009-07-15 14:48:32 +0000209/* --------- snprintf --------- */
210
sewardj45f4e7c2005-09-27 19:20:21 +0000211typedef
212 struct {
213 HChar* buf;
214 Int buf_size;
215 Int buf_used;
216 }
sewardj738856f2009-07-15 14:48:32 +0000217 snprintf_buf_t;
sewardj45f4e7c2005-09-27 19:20:21 +0000218
sewardj738856f2009-07-15 14:48:32 +0000219static void add_to__snprintf_buf ( HChar c, void* p )
sewardj45f4e7c2005-09-27 19:20:21 +0000220{
sewardj738856f2009-07-15 14:48:32 +0000221 snprintf_buf_t* b = p;
sewardj45f4e7c2005-09-27 19:20:21 +0000222 if (b->buf_size > 0 && b->buf_used < b->buf_size) {
223 b->buf[b->buf_used++] = c;
224 if (b->buf_used < b->buf_size)
225 b->buf[b->buf_used] = 0;
sewardj03e2bb82006-12-24 03:02:18 +0000226 else
227 b->buf[b->buf_size-1] = 0; /* pre: b->buf_size > 0 */
sewardj45f4e7c2005-09-27 19:20:21 +0000228 }
229}
230
floriandbb35842012-10-27 18:39:11 +0000231UInt VG_(vsnprintf) ( HChar* buf, Int size, const HChar *format, va_list vargs )
sewardj45f4e7c2005-09-27 19:20:21 +0000232{
sewardj738856f2009-07-15 14:48:32 +0000233 snprintf_buf_t b;
sewardj45f4e7c2005-09-27 19:20:21 +0000234 b.buf = buf;
235 b.buf_size = size < 0 ? 0 : size;
236 b.buf_used = 0;
philippe3a00f522013-02-26 21:54:28 +0000237 if (b.buf_size > 0)
238 b.buf[0] = 0; // ensure to null terminate buf if empty format
sewardjc7ffc942011-03-28 16:26:42 +0000239 (void) VG_(debugLog_vprintf)
240 ( add_to__snprintf_buf, &b, format, vargs );
sewardj45f4e7c2005-09-27 19:20:21 +0000241
242 return b.buf_used;
243}
244
floriandbb35842012-10-27 18:39:11 +0000245UInt VG_(snprintf) ( HChar* buf, Int size, const HChar *format, ... )
sewardj45f4e7c2005-09-27 19:20:21 +0000246{
247 UInt ret;
248 va_list vargs;
sewardj45f4e7c2005-09-27 19:20:21 +0000249 va_start(vargs,format);
250 ret = VG_(vsnprintf)(buf, size, format, vargs);
251 va_end(vargs);
sewardj45f4e7c2005-09-27 19:20:21 +0000252 return ret;
253}
254
255
sewardj738856f2009-07-15 14:48:32 +0000256/* --------- vcbprintf --------- */
257
258void VG_(vcbprintf)( void(*char_sink)(HChar, void* opaque),
259 void* opaque,
260 const HChar* format, va_list vargs )
261{
262 (void) VG_(debugLog_vprintf)
263 ( char_sink, opaque, format, vargs );
264}
265
266
njnc44a6c22005-06-03 13:21:18 +0000267/* ---------------------------------------------------------------------
njn856c54e2005-06-26 18:43:40 +0000268 percentify()
269 ------------------------------------------------------------------ */
270
njn7a5915e2005-07-17 16:12:59 +0000271// Percentify n/m with d decimal places. Includes the '%' symbol at the end.
njn5eaff2f2005-09-25 19:11:45 +0000272// Right justifies in 'buf'.
floriandbb35842012-10-27 18:39:11 +0000273void VG_(percentify)(ULong n, ULong m, UInt d, Int n_buf, HChar buf[])
njn856c54e2005-06-26 18:43:40 +0000274{
275 Int i, len, space;
njn641e6162005-07-17 16:16:41 +0000276 ULong p1;
floriandbb35842012-10-27 18:39:11 +0000277 HChar fmt[32];
njn856c54e2005-06-26 18:43:40 +0000278
njn641e6162005-07-17 16:16:41 +0000279 if (m == 0) {
njn5eaff2f2005-09-25 19:11:45 +0000280 // Have to generate the format string in order to be flexible about
281 // the width of the field.
njn8a7b41b2007-09-23 00:51:24 +0000282 VG_(sprintf)(fmt, "%%-%ds", n_buf);
njn5eaff2f2005-09-25 19:11:45 +0000283 // fmt is now "%<n_buf>s" where <d> is 1,2,3...
284 VG_(sprintf)(buf, fmt, "--%");
njn641e6162005-07-17 16:16:41 +0000285 return;
286 }
287
288 p1 = (100*n) / m;
njn856c54e2005-06-26 18:43:40 +0000289
290 if (d == 0) {
291 VG_(sprintf)(buf, "%lld%%", p1);
292 } else {
293 ULong p2;
294 UInt ex;
njn856c54e2005-06-26 18:43:40 +0000295 switch (d) {
296 case 1: ex = 10; break;
297 case 2: ex = 100; break;
298 case 3: ex = 1000; break;
299 default: VG_(tool_panic)("Currently can only handle 3 decimal places");
300 }
301 p2 = ((100*n*ex) / m) % ex;
302 // Have to generate the format string in order to be flexible about
303 // the width of the post-decimal-point part.
304 VG_(sprintf)(fmt, "%%lld.%%0%dlld%%%%", d);
305 // fmt is now "%lld.%0<d>lld%%" where <d> is 1,2,3...
306 VG_(sprintf)(buf, fmt, p1, p2);
307 }
308
309 len = VG_(strlen)(buf);
310 space = n_buf - len;
311 if (space < 0) space = 0; /* Allow for v. small field_width */
312 i = len;
313
314 /* Right justify in field */
315 for ( ; i >= 0; i--) buf[i + space] = buf[i];
316 for (i = 0; i < space; i++) buf[i] = ' ';
317}
318
sewardja11553a2005-07-19 12:17:05 +0000319
320/* ---------------------------------------------------------------------
sewardj592ae092005-11-08 19:01:44 +0000321 elapsed_wallclock_time()
sewardja11553a2005-07-19 12:17:05 +0000322 ------------------------------------------------------------------ */
323
sewardj592ae092005-11-08 19:01:44 +0000324/* Get the elapsed wallclock time since startup into buf, which must
325 16 chars long. This is unchecked. It also relies on the
326 millisecond timer having been set to zero by an initial read in
327 m_main during startup. */
sewardja11553a2005-07-19 12:17:05 +0000328
sewardj592ae092005-11-08 19:01:44 +0000329void VG_(elapsed_wallclock_time) ( /*OUT*/HChar* buf )
sewardja11553a2005-07-19 12:17:05 +0000330{
sewardj592ae092005-11-08 19:01:44 +0000331 UInt t, ms, s, mins, hours, days;
332
333 t = VG_(read_millisecond_timer)(); /* milliseconds */
334
335 ms = t % 1000;
336 t /= 1000; /* now in seconds */
337
338 s = t % 60;
339 t /= 60; /* now in minutes */
340
341 mins = t % 60;
342 t /= 60; /* now in hours */
343
344 hours = t % 24;
345 t /= 24; /* now in days */
346
347 days = t;
348
njn82baca72009-07-24 05:35:49 +0000349 VG_(sprintf)(buf, "%02u:%02u:%02u:%02u.%03u ", days, hours, mins, s, ms);
sewardja11553a2005-07-19 12:17:05 +0000350}
351
352
njn856c54e2005-06-26 18:43:40 +0000353/* ---------------------------------------------------------------------
njnc44a6c22005-06-03 13:21:18 +0000354 message()
355 ------------------------------------------------------------------ */
356
sewardj738856f2009-07-15 14:48:32 +0000357/* A buffer for accumulating VG_(message) style output. This is
358 pretty much the same as VG_(printf)'s scheme, with two differences:
359
360 * The message buffer persists between calls, so that multiple
361 calls to VG_(message) can build up output.
362
363 * Whenever the first character on a line is emitted, the
364 ==PID== style preamble is stuffed in before it.
365*/
366typedef
367 struct {
368 HChar buf[512+128];
369 Int buf_used;
370 Bool atLeft; /* notionally, is the next char position at the
371 leftmost column? */
372 /* Current message kind - changes from call to call */
373 VgMsgKind kind;
sewardj738856f2009-07-15 14:48:32 +0000374 /* destination */
375 OutputSink* sink;
376 }
377 vmessage_buf_t;
378
379static vmessage_buf_t vmessage_buf
sewardj8ddb93a2010-02-15 10:07:05 +0000380 = { "", 0, True, Vg_UserMsg, &VG_(log_output_sink) };
sewardj738856f2009-07-15 14:48:32 +0000381
382
383// Adds a single char to the buffer. We aim to have at least 128
384// bytes free in the buffer, so that it's always possible to emit
385// the preamble into the buffer if c happens to be the character
386// following a \n. When the buffer gets too full, we write its
387// contents to the logging sink.
388static void add_to__vmessage_buf ( HChar c, void *p )
389{
390 HChar tmp[64];
391 vmessage_buf_t* b = (vmessage_buf_t*)p;
392
393 vg_assert(b->buf_used >= 0 && b->buf_used < sizeof(b->buf)-128);
394
395 if (UNLIKELY(b->atLeft)) {
396 // insert preamble
397 HChar ch;
398 Int i, depth;
399
sewardj738856f2009-07-15 14:48:32 +0000400 // Print one '>' in front of the messages for each level of
401 // self-hosting being performed.
philippe72faf102012-03-11 22:24:03 +0000402 // Do not print such '>' if sim hint "no-inner-prefix" given
403 // (useful to run regression tests in an outer/inner setup
404 // and avoid the diff failing due to these unexpected '>').
sewardj738856f2009-07-15 14:48:32 +0000405 depth = RUNNING_ON_VALGRIND;
philippe72faf102012-03-11 22:24:03 +0000406 if (depth > 0 && !VG_(strstr)(VG_(clo_sim_hints), "no-inner-prefix")) {
407 if (depth > 10)
408 depth = 10; // ?!?!
409 for (i = 0; i < depth; i++) {
410 b->buf[b->buf_used++] = '>';
411 }
sewardj738856f2009-07-15 14:48:32 +0000412 }
413
njnb1cc5d62010-07-06 04:05:23 +0000414 if (Vg_FailMsg == b->kind) {
415 // "valgrind: " prefix.
416 b->buf[b->buf_used++] = 'v';
417 b->buf[b->buf_used++] = 'a';
418 b->buf[b->buf_used++] = 'l';
419 b->buf[b->buf_used++] = 'g';
420 b->buf[b->buf_used++] = 'r';
421 b->buf[b->buf_used++] = 'i';
422 b->buf[b->buf_used++] = 'n';
423 b->buf[b->buf_used++] = 'd';
424 b->buf[b->buf_used++] = ':';
425 b->buf[b->buf_used++] = ' ';
426 } else {
427 switch (b->kind) {
428 case Vg_UserMsg: ch = '='; break;
429 case Vg_DebugMsg: ch = '-'; break;
njnb1cc5d62010-07-06 04:05:23 +0000430 case Vg_ClientMsg: ch = '*'; break;
431 default: ch = '?'; break;
432 }
sewardj738856f2009-07-15 14:48:32 +0000433
njnb1cc5d62010-07-06 04:05:23 +0000434 b->buf[b->buf_used++] = ch;
435 b->buf[b->buf_used++] = ch;
436
437 if (VG_(clo_time_stamp)) {
438 VG_(memset)(tmp, 0, sizeof(tmp));
439 VG_(elapsed_wallclock_time)(tmp);
440 tmp[sizeof(tmp)-1] = 0;
441 for (i = 0; tmp[i]; i++)
442 b->buf[b->buf_used++] = tmp[i];
443 }
444
445 VG_(sprintf)(tmp, "%d", VG_(getpid)());
sewardj738856f2009-07-15 14:48:32 +0000446 tmp[sizeof(tmp)-1] = 0;
447 for (i = 0; tmp[i]; i++)
448 b->buf[b->buf_used++] = tmp[i];
njnb1cc5d62010-07-06 04:05:23 +0000449
450 b->buf[b->buf_used++] = ch;
451 b->buf[b->buf_used++] = ch;
452 b->buf[b->buf_used++] = ' ';
sewardj738856f2009-07-15 14:48:32 +0000453 }
454
sewardj738856f2009-07-15 14:48:32 +0000455 /* We can't possibly have stuffed 96 chars in merely as a result
456 of making the preamble (can we?) */
457 vg_assert(b->buf_used < sizeof(b->buf)-32);
458 }
459
460 b->buf[b->buf_used++] = c;
461 b->buf[b->buf_used] = 0;
462
463 if (b->buf_used >= sizeof(b->buf) - 128) {
464 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
465 b->buf_used = 0;
466 }
467
468 b->atLeft = c == '\n';
469}
470
471
njnc44a6c22005-06-03 13:21:18 +0000472UInt VG_(vmessage) ( VgMsgKind kind, const HChar* format, va_list vargs )
473{
sewardj738856f2009-07-15 14:48:32 +0000474 UInt ret;
njnc44a6c22005-06-03 13:21:18 +0000475
sewardj738856f2009-07-15 14:48:32 +0000476 /* Note (carefully) that the buf persists from call to call, unlike
477 with the other printf variants in earlier parts of this file. */
478 vmessage_buf_t* b = &vmessage_buf; /* shorthand for convenience */
479
480 /* We have to set this each call, so that the correct flavour
481 of preamble is emitted at each \n. */
482 b->kind = kind;
483
sewardj738856f2009-07-15 14:48:32 +0000484 ret = VG_(debugLog_vprintf) ( add_to__vmessage_buf,
485 b, format, vargs );
njnc44a6c22005-06-03 13:21:18 +0000486
sewardj738856f2009-07-15 14:48:32 +0000487 /* If the message finished exactly with a \n, then flush it at this
488 point. If not, assume more bits of the same line will turn up
489 in later messages, so don't bother to flush it right now. */
490
491 if (b->atLeft && b->buf_used > 0) {
492 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
493 b->buf_used = 0;
njnc44a6c22005-06-03 13:21:18 +0000494 }
495
sewardj738856f2009-07-15 14:48:32 +0000496 return ret;
njnc44a6c22005-06-03 13:21:18 +0000497}
498
njnc44a6c22005-06-03 13:21:18 +0000499/* Send a simple single-part message. */
500UInt VG_(message) ( VgMsgKind kind, const HChar* format, ... )
501{
502 UInt count;
503 va_list vargs;
504 va_start(vargs,format);
505 count = VG_(vmessage) ( kind, format, vargs );
506 va_end(vargs);
507 return count;
508}
509
njnb1cc5d62010-07-06 04:05:23 +0000510static void revert_to_stderr ( void )
511{
512 VG_(log_output_sink).fd = 2; /* stderr */
513 VG_(log_output_sink).is_socket = False;
514}
515
sewardj738856f2009-07-15 14:48:32 +0000516/* VG_(message) variants with hardwired first argument. */
njnb1cc5d62010-07-06 04:05:23 +0000517
518UInt VG_(fmsg) ( const HChar* format, ... )
519{
520 UInt count;
521 va_list vargs;
522 va_start(vargs,format);
523 count = VG_(vmessage) ( Vg_FailMsg, format, vargs );
524 va_end(vargs);
525 return count;
526}
527
florianbbd9a212012-10-14 00:16:28 +0000528void VG_(fmsg_bad_option) ( const HChar* opt, const HChar* format, ... )
njnb1cc5d62010-07-06 04:05:23 +0000529{
530 va_list vargs;
531 va_start(vargs,format);
532 revert_to_stderr();
533 VG_(message) (Vg_FailMsg, "Bad option: %s\n", opt);
534 VG_(vmessage)(Vg_FailMsg, format, vargs );
535 VG_(message) (Vg_FailMsg, "Use --help for more information or consult the user manual.\n");
536 VG_(exit)(1);
537 va_end(vargs);
538}
539
sewardj738856f2009-07-15 14:48:32 +0000540UInt VG_(umsg) ( const HChar* format, ... )
541{
542 UInt count;
543 va_list vargs;
544 va_start(vargs,format);
545 count = VG_(vmessage) ( Vg_UserMsg, format, vargs );
546 va_end(vargs);
547 return count;
548}
549
550UInt VG_(dmsg) ( const HChar* format, ... )
551{
552 UInt count;
553 va_list vargs;
554 va_start(vargs,format);
555 count = VG_(vmessage) ( Vg_DebugMsg, format, vargs );
556 va_end(vargs);
557 return count;
558}
559
sewardj738856f2009-07-15 14:48:32 +0000560/* Flush any output that has accumulated in vmessage_buf as a
561 result of previous calls to VG_(message) et al. */
562void VG_(message_flush) ( void )
563{
564 vmessage_buf_t* b = &vmessage_buf;
565 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
566 b->buf_used = 0;
567}
568
njnb1cc5d62010-07-06 04:05:23 +0000569__attribute__((noreturn))
570void VG_(err_missing_prog) ( void )
571{
572 revert_to_stderr();
573 VG_(fmsg)("no program specified\n");
574 VG_(fmsg)("Use --help for more information.\n");
575 VG_(exit)(1);
576}
577
578__attribute__((noreturn))
florianbbd9a212012-10-14 00:16:28 +0000579void VG_(err_config_error) ( const HChar* format, ... )
njnb1cc5d62010-07-06 04:05:23 +0000580{
florian1763e812011-07-12 19:07:05 +0000581 va_list vargs;
582 va_start(vargs,format);
njnb1cc5d62010-07-06 04:05:23 +0000583 revert_to_stderr();
florian1763e812011-07-12 19:07:05 +0000584 VG_(message) (Vg_FailMsg, "Startup or configuration error:\n ");
585 VG_(vmessage)(Vg_FailMsg, format, vargs );
586 VG_(message) (Vg_FailMsg, "Unable to start up properly. Giving up.\n");
njnb1cc5d62010-07-06 04:05:23 +0000587 VG_(exit)(1);
florian1763e812011-07-12 19:07:05 +0000588 va_end(vargs);
njnb1cc5d62010-07-06 04:05:23 +0000589}
590
sewardj738856f2009-07-15 14:48:32 +0000591
njnc44a6c22005-06-03 13:21:18 +0000592/*--------------------------------------------------------------------*/
593/*--- end ---*/
594/*--------------------------------------------------------------------*/
595