blob: 46b488a5e84bc0b770319c360dd4ceeb78fed4ab [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
sewardj0f157dd2013-10-18 14:27:36 +000010 Copyright (C) 2000-2013 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"
florian1a046d52013-09-16 20:56:35 +000041#include "pub_core_clreq.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
philippe07c08522014-05-14 20:39:27 +0000171static UInt emit_WRK ( const HChar* format, va_list vargs )
172{
173 if (VG_(clo_xml)) {
174 return VG_(vprintf_xml)(format, vargs);
175 } else if (VG_(log_output_sink).fd == -2) {
176 return VG_(vprintf) (format, vargs);
177 } else {
178 return VG_(vmessage)(Vg_UserMsg, format, vargs);
179 }
180}
181UInt VG_(emit) ( const HChar* format, ... )
182{
183 UInt ret;
184 va_list vargs;
185 va_start(vargs, format);
186 ret = emit_WRK(format, vargs);
187 va_end(vargs);
188 return ret;
189}
sewardj738856f2009-07-15 14:48:32 +0000190
191/* --------- sprintf --------- */
192
193/* If we had an explicit buf structure here, it would contain only one
194 field, indicating where the next char is to go. So use p directly
195 for that, rather than having it be a pointer to a structure. */
196
197static void add_to__sprintf_buf ( HChar c, void *p )
198{
199 HChar** b = p;
200 *(*b)++ = c;
njnc44a6c22005-06-03 13:21:18 +0000201}
202
floriandbb35842012-10-27 18:39:11 +0000203UInt VG_(vsprintf) ( HChar* buf, const HChar *format, va_list vargs )
njnc44a6c22005-06-03 13:21:18 +0000204{
205 Int ret;
sewardj738856f2009-07-15 14:48:32 +0000206 HChar* sprintf_ptr = buf;
njnc44a6c22005-06-03 13:21:18 +0000207
208 ret = VG_(debugLog_vprintf)
sewardj738856f2009-07-15 14:48:32 +0000209 ( add_to__sprintf_buf, &sprintf_ptr, format, vargs );
210 add_to__sprintf_buf('\0', &sprintf_ptr);
njnc44a6c22005-06-03 13:21:18 +0000211
212 vg_assert(VG_(strlen)(buf) == ret);
213
214 return ret;
215}
216
floriandbb35842012-10-27 18:39:11 +0000217UInt VG_(sprintf) ( HChar* buf, const HChar *format, ... )
njnc44a6c22005-06-03 13:21:18 +0000218{
219 UInt ret;
220 va_list vargs;
njnc44a6c22005-06-03 13:21:18 +0000221 va_start(vargs,format);
222 ret = VG_(vsprintf)(buf, format, vargs);
223 va_end(vargs);
njnc44a6c22005-06-03 13:21:18 +0000224 return ret;
225}
226
sewardj45f4e7c2005-09-27 19:20:21 +0000227
sewardj738856f2009-07-15 14:48:32 +0000228/* --------- snprintf --------- */
229
sewardj45f4e7c2005-09-27 19:20:21 +0000230typedef
231 struct {
232 HChar* buf;
233 Int buf_size;
234 Int buf_used;
235 }
sewardj738856f2009-07-15 14:48:32 +0000236 snprintf_buf_t;
sewardj45f4e7c2005-09-27 19:20:21 +0000237
sewardj738856f2009-07-15 14:48:32 +0000238static void add_to__snprintf_buf ( HChar c, void* p )
sewardj45f4e7c2005-09-27 19:20:21 +0000239{
sewardj738856f2009-07-15 14:48:32 +0000240 snprintf_buf_t* b = p;
sewardj45f4e7c2005-09-27 19:20:21 +0000241 if (b->buf_size > 0 && b->buf_used < b->buf_size) {
242 b->buf[b->buf_used++] = c;
243 if (b->buf_used < b->buf_size)
244 b->buf[b->buf_used] = 0;
sewardj03e2bb82006-12-24 03:02:18 +0000245 else
246 b->buf[b->buf_size-1] = 0; /* pre: b->buf_size > 0 */
sewardj45f4e7c2005-09-27 19:20:21 +0000247 }
248}
249
floriandbb35842012-10-27 18:39:11 +0000250UInt VG_(vsnprintf) ( HChar* buf, Int size, const HChar *format, va_list vargs )
sewardj45f4e7c2005-09-27 19:20:21 +0000251{
sewardj738856f2009-07-15 14:48:32 +0000252 snprintf_buf_t b;
sewardj45f4e7c2005-09-27 19:20:21 +0000253 b.buf = buf;
254 b.buf_size = size < 0 ? 0 : size;
255 b.buf_used = 0;
philippe3a00f522013-02-26 21:54:28 +0000256 if (b.buf_size > 0)
257 b.buf[0] = 0; // ensure to null terminate buf if empty format
sewardjc7ffc942011-03-28 16:26:42 +0000258 (void) VG_(debugLog_vprintf)
259 ( add_to__snprintf_buf, &b, format, vargs );
sewardj45f4e7c2005-09-27 19:20:21 +0000260
261 return b.buf_used;
262}
263
floriandbb35842012-10-27 18:39:11 +0000264UInt VG_(snprintf) ( HChar* buf, Int size, const HChar *format, ... )
sewardj45f4e7c2005-09-27 19:20:21 +0000265{
266 UInt ret;
267 va_list vargs;
sewardj45f4e7c2005-09-27 19:20:21 +0000268 va_start(vargs,format);
269 ret = VG_(vsnprintf)(buf, size, format, vargs);
270 va_end(vargs);
sewardj45f4e7c2005-09-27 19:20:21 +0000271 return ret;
272}
273
274
sewardj738856f2009-07-15 14:48:32 +0000275/* --------- vcbprintf --------- */
276
277void VG_(vcbprintf)( void(*char_sink)(HChar, void* opaque),
278 void* opaque,
279 const HChar* format, va_list vargs )
280{
281 (void) VG_(debugLog_vprintf)
282 ( char_sink, opaque, format, vargs );
283}
284
285
njnc44a6c22005-06-03 13:21:18 +0000286/* ---------------------------------------------------------------------
njn856c54e2005-06-26 18:43:40 +0000287 percentify()
288 ------------------------------------------------------------------ */
289
njn7a5915e2005-07-17 16:12:59 +0000290// Percentify n/m with d decimal places. Includes the '%' symbol at the end.
njn5eaff2f2005-09-25 19:11:45 +0000291// Right justifies in 'buf'.
floriandbb35842012-10-27 18:39:11 +0000292void VG_(percentify)(ULong n, ULong m, UInt d, Int n_buf, HChar buf[])
njn856c54e2005-06-26 18:43:40 +0000293{
294 Int i, len, space;
njn641e6162005-07-17 16:16:41 +0000295 ULong p1;
floriandbb35842012-10-27 18:39:11 +0000296 HChar fmt[32];
njn856c54e2005-06-26 18:43:40 +0000297
njn641e6162005-07-17 16:16:41 +0000298 if (m == 0) {
njn5eaff2f2005-09-25 19:11:45 +0000299 // Have to generate the format string in order to be flexible about
300 // the width of the field.
njn8a7b41b2007-09-23 00:51:24 +0000301 VG_(sprintf)(fmt, "%%-%ds", n_buf);
njn5eaff2f2005-09-25 19:11:45 +0000302 // fmt is now "%<n_buf>s" where <d> is 1,2,3...
303 VG_(sprintf)(buf, fmt, "--%");
njn641e6162005-07-17 16:16:41 +0000304 return;
305 }
306
307 p1 = (100*n) / m;
njn856c54e2005-06-26 18:43:40 +0000308
309 if (d == 0) {
310 VG_(sprintf)(buf, "%lld%%", p1);
311 } else {
312 ULong p2;
313 UInt ex;
njn856c54e2005-06-26 18:43:40 +0000314 switch (d) {
315 case 1: ex = 10; break;
316 case 2: ex = 100; break;
317 case 3: ex = 1000; break;
318 default: VG_(tool_panic)("Currently can only handle 3 decimal places");
319 }
320 p2 = ((100*n*ex) / m) % ex;
321 // Have to generate the format string in order to be flexible about
322 // the width of the post-decimal-point part.
323 VG_(sprintf)(fmt, "%%lld.%%0%dlld%%%%", d);
324 // fmt is now "%lld.%0<d>lld%%" where <d> is 1,2,3...
325 VG_(sprintf)(buf, fmt, p1, p2);
326 }
327
328 len = VG_(strlen)(buf);
329 space = n_buf - len;
330 if (space < 0) space = 0; /* Allow for v. small field_width */
331 i = len;
332
333 /* Right justify in field */
334 for ( ; i >= 0; i--) buf[i + space] = buf[i];
335 for (i = 0; i < space; i++) buf[i] = ' ';
336}
337
sewardja11553a2005-07-19 12:17:05 +0000338
339/* ---------------------------------------------------------------------
sewardj592ae092005-11-08 19:01:44 +0000340 elapsed_wallclock_time()
sewardja11553a2005-07-19 12:17:05 +0000341 ------------------------------------------------------------------ */
342
sewardj592ae092005-11-08 19:01:44 +0000343/* Get the elapsed wallclock time since startup into buf, which must
344 16 chars long. This is unchecked. It also relies on the
345 millisecond timer having been set to zero by an initial read in
346 m_main during startup. */
sewardja11553a2005-07-19 12:17:05 +0000347
sewardj592ae092005-11-08 19:01:44 +0000348void VG_(elapsed_wallclock_time) ( /*OUT*/HChar* buf )
sewardja11553a2005-07-19 12:17:05 +0000349{
sewardj592ae092005-11-08 19:01:44 +0000350 UInt t, ms, s, mins, hours, days;
351
352 t = VG_(read_millisecond_timer)(); /* milliseconds */
353
354 ms = t % 1000;
355 t /= 1000; /* now in seconds */
356
357 s = t % 60;
358 t /= 60; /* now in minutes */
359
360 mins = t % 60;
361 t /= 60; /* now in hours */
362
363 hours = t % 24;
364 t /= 24; /* now in days */
365
366 days = t;
367
njn82baca72009-07-24 05:35:49 +0000368 VG_(sprintf)(buf, "%02u:%02u:%02u:%02u.%03u ", days, hours, mins, s, ms);
sewardja11553a2005-07-19 12:17:05 +0000369}
370
371
njn856c54e2005-06-26 18:43:40 +0000372/* ---------------------------------------------------------------------
njnc44a6c22005-06-03 13:21:18 +0000373 message()
374 ------------------------------------------------------------------ */
375
sewardj738856f2009-07-15 14:48:32 +0000376/* A buffer for accumulating VG_(message) style output. This is
377 pretty much the same as VG_(printf)'s scheme, with two differences:
378
379 * The message buffer persists between calls, so that multiple
380 calls to VG_(message) can build up output.
381
382 * Whenever the first character on a line is emitted, the
383 ==PID== style preamble is stuffed in before it.
384*/
385typedef
386 struct {
387 HChar buf[512+128];
388 Int buf_used;
389 Bool atLeft; /* notionally, is the next char position at the
390 leftmost column? */
391 /* Current message kind - changes from call to call */
392 VgMsgKind kind;
sewardj738856f2009-07-15 14:48:32 +0000393 /* destination */
394 OutputSink* sink;
395 }
396 vmessage_buf_t;
397
398static vmessage_buf_t vmessage_buf
sewardj8ddb93a2010-02-15 10:07:05 +0000399 = { "", 0, True, Vg_UserMsg, &VG_(log_output_sink) };
sewardj738856f2009-07-15 14:48:32 +0000400
401
402// Adds a single char to the buffer. We aim to have at least 128
403// bytes free in the buffer, so that it's always possible to emit
404// the preamble into the buffer if c happens to be the character
405// following a \n. When the buffer gets too full, we write its
406// contents to the logging sink.
407static void add_to__vmessage_buf ( HChar c, void *p )
408{
409 HChar tmp[64];
410 vmessage_buf_t* b = (vmessage_buf_t*)p;
411
412 vg_assert(b->buf_used >= 0 && b->buf_used < sizeof(b->buf)-128);
413
414 if (UNLIKELY(b->atLeft)) {
415 // insert preamble
416 HChar ch;
417 Int i, depth;
418
sewardj738856f2009-07-15 14:48:32 +0000419 // Print one '>' in front of the messages for each level of
420 // self-hosting being performed.
philippe72faf102012-03-11 22:24:03 +0000421 // Do not print such '>' if sim hint "no-inner-prefix" given
422 // (useful to run regression tests in an outer/inner setup
423 // and avoid the diff failing due to these unexpected '>').
sewardj738856f2009-07-15 14:48:32 +0000424 depth = RUNNING_ON_VALGRIND;
philippeec905f72014-08-17 20:03:51 +0000425 if (depth > 0
426 && !SimHintiS(SimHint_no_inner_prefix, VG_(clo_sim_hints))) {
philippe72faf102012-03-11 22:24:03 +0000427 if (depth > 10)
428 depth = 10; // ?!?!
429 for (i = 0; i < depth; i++) {
430 b->buf[b->buf_used++] = '>';
431 }
sewardj738856f2009-07-15 14:48:32 +0000432 }
433
njnb1cc5d62010-07-06 04:05:23 +0000434 if (Vg_FailMsg == b->kind) {
435 // "valgrind: " prefix.
436 b->buf[b->buf_used++] = 'v';
437 b->buf[b->buf_used++] = 'a';
438 b->buf[b->buf_used++] = 'l';
439 b->buf[b->buf_used++] = 'g';
440 b->buf[b->buf_used++] = 'r';
441 b->buf[b->buf_used++] = 'i';
442 b->buf[b->buf_used++] = 'n';
443 b->buf[b->buf_used++] = 'd';
444 b->buf[b->buf_used++] = ':';
445 b->buf[b->buf_used++] = ' ';
446 } else {
447 switch (b->kind) {
448 case Vg_UserMsg: ch = '='; break;
449 case Vg_DebugMsg: ch = '-'; break;
njnb1cc5d62010-07-06 04:05:23 +0000450 case Vg_ClientMsg: ch = '*'; break;
451 default: ch = '?'; break;
452 }
sewardj738856f2009-07-15 14:48:32 +0000453
njnb1cc5d62010-07-06 04:05:23 +0000454 b->buf[b->buf_used++] = ch;
455 b->buf[b->buf_used++] = ch;
456
457 if (VG_(clo_time_stamp)) {
458 VG_(memset)(tmp, 0, sizeof(tmp));
459 VG_(elapsed_wallclock_time)(tmp);
460 tmp[sizeof(tmp)-1] = 0;
461 for (i = 0; tmp[i]; i++)
462 b->buf[b->buf_used++] = tmp[i];
463 }
464
465 VG_(sprintf)(tmp, "%d", VG_(getpid)());
sewardj738856f2009-07-15 14:48:32 +0000466 tmp[sizeof(tmp)-1] = 0;
467 for (i = 0; tmp[i]; i++)
468 b->buf[b->buf_used++] = tmp[i];
njnb1cc5d62010-07-06 04:05:23 +0000469
470 b->buf[b->buf_used++] = ch;
471 b->buf[b->buf_used++] = ch;
472 b->buf[b->buf_used++] = ' ';
sewardj738856f2009-07-15 14:48:32 +0000473 }
474
sewardj738856f2009-07-15 14:48:32 +0000475 /* We can't possibly have stuffed 96 chars in merely as a result
476 of making the preamble (can we?) */
477 vg_assert(b->buf_used < sizeof(b->buf)-32);
478 }
479
480 b->buf[b->buf_used++] = c;
481 b->buf[b->buf_used] = 0;
482
483 if (b->buf_used >= sizeof(b->buf) - 128) {
484 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
485 b->buf_used = 0;
486 }
487
488 b->atLeft = c == '\n';
489}
490
491
njnc44a6c22005-06-03 13:21:18 +0000492UInt VG_(vmessage) ( VgMsgKind kind, const HChar* format, va_list vargs )
493{
sewardj738856f2009-07-15 14:48:32 +0000494 UInt ret;
njnc44a6c22005-06-03 13:21:18 +0000495
sewardj738856f2009-07-15 14:48:32 +0000496 /* Note (carefully) that the buf persists from call to call, unlike
497 with the other printf variants in earlier parts of this file. */
498 vmessage_buf_t* b = &vmessage_buf; /* shorthand for convenience */
499
500 /* We have to set this each call, so that the correct flavour
501 of preamble is emitted at each \n. */
502 b->kind = kind;
503
sewardj738856f2009-07-15 14:48:32 +0000504 ret = VG_(debugLog_vprintf) ( add_to__vmessage_buf,
505 b, format, vargs );
njnc44a6c22005-06-03 13:21:18 +0000506
sewardj738856f2009-07-15 14:48:32 +0000507 /* If the message finished exactly with a \n, then flush it at this
508 point. If not, assume more bits of the same line will turn up
509 in later messages, so don't bother to flush it right now. */
510
511 if (b->atLeft && b->buf_used > 0) {
512 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
513 b->buf_used = 0;
njnc44a6c22005-06-03 13:21:18 +0000514 }
515
sewardj738856f2009-07-15 14:48:32 +0000516 return ret;
njnc44a6c22005-06-03 13:21:18 +0000517}
518
njnc44a6c22005-06-03 13:21:18 +0000519/* Send a simple single-part message. */
520UInt VG_(message) ( VgMsgKind kind, const HChar* format, ... )
521{
522 UInt count;
523 va_list vargs;
524 va_start(vargs,format);
525 count = VG_(vmessage) ( kind, format, vargs );
526 va_end(vargs);
527 return count;
528}
529
njnb1cc5d62010-07-06 04:05:23 +0000530static void revert_to_stderr ( void )
531{
532 VG_(log_output_sink).fd = 2; /* stderr */
533 VG_(log_output_sink).is_socket = False;
534}
535
sewardj738856f2009-07-15 14:48:32 +0000536/* VG_(message) variants with hardwired first argument. */
njnb1cc5d62010-07-06 04:05:23 +0000537
538UInt VG_(fmsg) ( const HChar* format, ... )
539{
540 UInt count;
541 va_list vargs;
542 va_start(vargs,format);
543 count = VG_(vmessage) ( Vg_FailMsg, format, vargs );
544 va_end(vargs);
545 return count;
546}
547
florianbbd9a212012-10-14 00:16:28 +0000548void VG_(fmsg_bad_option) ( const HChar* opt, const HChar* format, ... )
njnb1cc5d62010-07-06 04:05:23 +0000549{
550 va_list vargs;
551 va_start(vargs,format);
552 revert_to_stderr();
553 VG_(message) (Vg_FailMsg, "Bad option: %s\n", opt);
554 VG_(vmessage)(Vg_FailMsg, format, vargs );
555 VG_(message) (Vg_FailMsg, "Use --help for more information or consult the user manual.\n");
556 VG_(exit)(1);
557 va_end(vargs);
558}
559
sewardj738856f2009-07-15 14:48:32 +0000560UInt VG_(umsg) ( const HChar* format, ... )
561{
562 UInt count;
563 va_list vargs;
564 va_start(vargs,format);
565 count = VG_(vmessage) ( Vg_UserMsg, format, vargs );
566 va_end(vargs);
567 return count;
568}
569
570UInt VG_(dmsg) ( const HChar* format, ... )
571{
572 UInt count;
573 va_list vargs;
574 va_start(vargs,format);
575 count = VG_(vmessage) ( Vg_DebugMsg, format, vargs );
576 va_end(vargs);
577 return count;
578}
579
sewardj738856f2009-07-15 14:48:32 +0000580/* Flush any output that has accumulated in vmessage_buf as a
581 result of previous calls to VG_(message) et al. */
582void VG_(message_flush) ( void )
583{
584 vmessage_buf_t* b = &vmessage_buf;
585 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
586 b->buf_used = 0;
587}
588
njnb1cc5d62010-07-06 04:05:23 +0000589__attribute__((noreturn))
590void VG_(err_missing_prog) ( void )
591{
592 revert_to_stderr();
593 VG_(fmsg)("no program specified\n");
594 VG_(fmsg)("Use --help for more information.\n");
595 VG_(exit)(1);
596}
597
598__attribute__((noreturn))
florianbbd9a212012-10-14 00:16:28 +0000599void VG_(err_config_error) ( const HChar* format, ... )
njnb1cc5d62010-07-06 04:05:23 +0000600{
florian1763e812011-07-12 19:07:05 +0000601 va_list vargs;
602 va_start(vargs,format);
njnb1cc5d62010-07-06 04:05:23 +0000603 revert_to_stderr();
florian1763e812011-07-12 19:07:05 +0000604 VG_(message) (Vg_FailMsg, "Startup or configuration error:\n ");
605 VG_(vmessage)(Vg_FailMsg, format, vargs );
606 VG_(message) (Vg_FailMsg, "Unable to start up properly. Giving up.\n");
njnb1cc5d62010-07-06 04:05:23 +0000607 VG_(exit)(1);
florian1763e812011-07-12 19:07:05 +0000608 va_end(vargs);
njnb1cc5d62010-07-06 04:05:23 +0000609}
610
sewardj738856f2009-07-15 14:48:32 +0000611
njnc44a6c22005-06-03 13:21:18 +0000612/*--------------------------------------------------------------------*/
613/*--- end ---*/
614/*--------------------------------------------------------------------*/
615