blob: cdeabb2b92e9eaea835425c804ef0e59c0767beb [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;
floriane2800c92014-09-15 20:57:45 +0000111 vg_assert(b->buf_used < sizeof(b->buf));
sewardj738856f2009-07-15 14:48:32 +0000112}
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
florian3e81b8b2014-10-07 14:28:52 +0000230/* The return value of VG_(snprintf) and VG_(vsnprintf) differs from
231 what is defined in C99. Let S be the size of the buffer as given in
232 the 2nd argument.
233 Return value R:
234 R < S: The output string was successfully written to the buffer.
235 It is null-terminated and R == strlen( output string )
236 R == S: The supplied buffer was too small to hold the output string.
237 The first S-1 characters of the output string were written
238 to the buffer followed by the terminating null character.
239*/
240
sewardj45f4e7c2005-09-27 19:20:21 +0000241typedef
242 struct {
243 HChar* buf;
244 Int buf_size;
245 Int buf_used;
246 }
sewardj738856f2009-07-15 14:48:32 +0000247 snprintf_buf_t;
sewardj45f4e7c2005-09-27 19:20:21 +0000248
sewardj738856f2009-07-15 14:48:32 +0000249static void add_to__snprintf_buf ( HChar c, void* p )
sewardj45f4e7c2005-09-27 19:20:21 +0000250{
sewardj738856f2009-07-15 14:48:32 +0000251 snprintf_buf_t* b = p;
sewardj45f4e7c2005-09-27 19:20:21 +0000252 if (b->buf_size > 0 && b->buf_used < b->buf_size) {
253 b->buf[b->buf_used++] = c;
254 if (b->buf_used < b->buf_size)
255 b->buf[b->buf_used] = 0;
sewardj03e2bb82006-12-24 03:02:18 +0000256 else
257 b->buf[b->buf_size-1] = 0; /* pre: b->buf_size > 0 */
sewardj45f4e7c2005-09-27 19:20:21 +0000258 }
259}
260
floriandbb35842012-10-27 18:39:11 +0000261UInt VG_(vsnprintf) ( HChar* buf, Int size, const HChar *format, va_list vargs )
sewardj45f4e7c2005-09-27 19:20:21 +0000262{
sewardj738856f2009-07-15 14:48:32 +0000263 snprintf_buf_t b;
sewardj45f4e7c2005-09-27 19:20:21 +0000264 b.buf = buf;
265 b.buf_size = size < 0 ? 0 : size;
266 b.buf_used = 0;
philippe3a00f522013-02-26 21:54:28 +0000267 if (b.buf_size > 0)
268 b.buf[0] = 0; // ensure to null terminate buf if empty format
sewardjc7ffc942011-03-28 16:26:42 +0000269 (void) VG_(debugLog_vprintf)
270 ( add_to__snprintf_buf, &b, format, vargs );
sewardj45f4e7c2005-09-27 19:20:21 +0000271
272 return b.buf_used;
273}
274
floriandbb35842012-10-27 18:39:11 +0000275UInt VG_(snprintf) ( HChar* buf, Int size, const HChar *format, ... )
sewardj45f4e7c2005-09-27 19:20:21 +0000276{
277 UInt ret;
278 va_list vargs;
sewardj45f4e7c2005-09-27 19:20:21 +0000279 va_start(vargs,format);
280 ret = VG_(vsnprintf)(buf, size, format, vargs);
281 va_end(vargs);
sewardj45f4e7c2005-09-27 19:20:21 +0000282 return ret;
283}
284
285
sewardj738856f2009-07-15 14:48:32 +0000286/* --------- vcbprintf --------- */
287
288void VG_(vcbprintf)( void(*char_sink)(HChar, void* opaque),
289 void* opaque,
290 const HChar* format, va_list vargs )
291{
292 (void) VG_(debugLog_vprintf)
293 ( char_sink, opaque, format, vargs );
294}
295
296
njnc44a6c22005-06-03 13:21:18 +0000297/* ---------------------------------------------------------------------
njn856c54e2005-06-26 18:43:40 +0000298 percentify()
299 ------------------------------------------------------------------ */
300
njn7a5915e2005-07-17 16:12:59 +0000301// Percentify n/m with d decimal places. Includes the '%' symbol at the end.
njn5eaff2f2005-09-25 19:11:45 +0000302// Right justifies in 'buf'.
floriandbb35842012-10-27 18:39:11 +0000303void VG_(percentify)(ULong n, ULong m, UInt d, Int n_buf, HChar buf[])
njn856c54e2005-06-26 18:43:40 +0000304{
305 Int i, len, space;
njn641e6162005-07-17 16:16:41 +0000306 ULong p1;
floriandbb35842012-10-27 18:39:11 +0000307 HChar fmt[32];
njn856c54e2005-06-26 18:43:40 +0000308
njn641e6162005-07-17 16:16:41 +0000309 if (m == 0) {
njn5eaff2f2005-09-25 19:11:45 +0000310 // Have to generate the format string in order to be flexible about
311 // the width of the field.
njn8a7b41b2007-09-23 00:51:24 +0000312 VG_(sprintf)(fmt, "%%-%ds", n_buf);
njn5eaff2f2005-09-25 19:11:45 +0000313 // fmt is now "%<n_buf>s" where <d> is 1,2,3...
314 VG_(sprintf)(buf, fmt, "--%");
njn641e6162005-07-17 16:16:41 +0000315 return;
316 }
317
318 p1 = (100*n) / m;
njn856c54e2005-06-26 18:43:40 +0000319
320 if (d == 0) {
321 VG_(sprintf)(buf, "%lld%%", p1);
322 } else {
323 ULong p2;
324 UInt ex;
njn856c54e2005-06-26 18:43:40 +0000325 switch (d) {
326 case 1: ex = 10; break;
327 case 2: ex = 100; break;
328 case 3: ex = 1000; break;
floriana4ca4fe2014-09-16 09:28:12 +0000329 default: VG_(core_panic)("Currently can only handle 3 decimal places");
njn856c54e2005-06-26 18:43:40 +0000330 }
331 p2 = ((100*n*ex) / m) % ex;
332 // Have to generate the format string in order to be flexible about
333 // the width of the post-decimal-point part.
334 VG_(sprintf)(fmt, "%%lld.%%0%dlld%%%%", d);
335 // fmt is now "%lld.%0<d>lld%%" where <d> is 1,2,3...
336 VG_(sprintf)(buf, fmt, p1, p2);
337 }
338
339 len = VG_(strlen)(buf);
340 space = n_buf - len;
341 if (space < 0) space = 0; /* Allow for v. small field_width */
342 i = len;
343
344 /* Right justify in field */
345 for ( ; i >= 0; i--) buf[i + space] = buf[i];
346 for (i = 0; i < space; i++) buf[i] = ' ';
347}
348
sewardja11553a2005-07-19 12:17:05 +0000349
350/* ---------------------------------------------------------------------
sewardj592ae092005-11-08 19:01:44 +0000351 elapsed_wallclock_time()
sewardja11553a2005-07-19 12:17:05 +0000352 ------------------------------------------------------------------ */
353
sewardj592ae092005-11-08 19:01:44 +0000354/* Get the elapsed wallclock time since startup into buf, which must
355 16 chars long. This is unchecked. It also relies on the
356 millisecond timer having been set to zero by an initial read in
357 m_main during startup. */
sewardja11553a2005-07-19 12:17:05 +0000358
sewardj592ae092005-11-08 19:01:44 +0000359void VG_(elapsed_wallclock_time) ( /*OUT*/HChar* buf )
sewardja11553a2005-07-19 12:17:05 +0000360{
sewardj592ae092005-11-08 19:01:44 +0000361 UInt t, ms, s, mins, hours, days;
362
363 t = VG_(read_millisecond_timer)(); /* milliseconds */
364
365 ms = t % 1000;
366 t /= 1000; /* now in seconds */
367
368 s = t % 60;
369 t /= 60; /* now in minutes */
370
371 mins = t % 60;
372 t /= 60; /* now in hours */
373
374 hours = t % 24;
375 t /= 24; /* now in days */
376
377 days = t;
378
njn82baca72009-07-24 05:35:49 +0000379 VG_(sprintf)(buf, "%02u:%02u:%02u:%02u.%03u ", days, hours, mins, s, ms);
sewardja11553a2005-07-19 12:17:05 +0000380}
381
382
njn856c54e2005-06-26 18:43:40 +0000383/* ---------------------------------------------------------------------
njnc44a6c22005-06-03 13:21:18 +0000384 message()
385 ------------------------------------------------------------------ */
386
sewardj738856f2009-07-15 14:48:32 +0000387/* A buffer for accumulating VG_(message) style output. This is
388 pretty much the same as VG_(printf)'s scheme, with two differences:
389
390 * The message buffer persists between calls, so that multiple
391 calls to VG_(message) can build up output.
392
393 * Whenever the first character on a line is emitted, the
394 ==PID== style preamble is stuffed in before it.
395*/
396typedef
397 struct {
398 HChar buf[512+128];
399 Int buf_used;
400 Bool atLeft; /* notionally, is the next char position at the
401 leftmost column? */
402 /* Current message kind - changes from call to call */
403 VgMsgKind kind;
sewardj738856f2009-07-15 14:48:32 +0000404 /* destination */
405 OutputSink* sink;
406 }
407 vmessage_buf_t;
408
409static vmessage_buf_t vmessage_buf
sewardj8ddb93a2010-02-15 10:07:05 +0000410 = { "", 0, True, Vg_UserMsg, &VG_(log_output_sink) };
sewardj738856f2009-07-15 14:48:32 +0000411
412
413// Adds a single char to the buffer. We aim to have at least 128
414// bytes free in the buffer, so that it's always possible to emit
415// the preamble into the buffer if c happens to be the character
416// following a \n. When the buffer gets too full, we write its
417// contents to the logging sink.
418static void add_to__vmessage_buf ( HChar c, void *p )
419{
420 HChar tmp[64];
421 vmessage_buf_t* b = (vmessage_buf_t*)p;
422
423 vg_assert(b->buf_used >= 0 && b->buf_used < sizeof(b->buf)-128);
424
425 if (UNLIKELY(b->atLeft)) {
426 // insert preamble
427 HChar ch;
428 Int i, depth;
429
sewardj738856f2009-07-15 14:48:32 +0000430 // Print one '>' in front of the messages for each level of
431 // self-hosting being performed.
philippe72faf102012-03-11 22:24:03 +0000432 // Do not print such '>' if sim hint "no-inner-prefix" given
433 // (useful to run regression tests in an outer/inner setup
434 // and avoid the diff failing due to these unexpected '>').
sewardj738856f2009-07-15 14:48:32 +0000435 depth = RUNNING_ON_VALGRIND;
philippeec905f72014-08-17 20:03:51 +0000436 if (depth > 0
437 && !SimHintiS(SimHint_no_inner_prefix, VG_(clo_sim_hints))) {
philippe72faf102012-03-11 22:24:03 +0000438 if (depth > 10)
439 depth = 10; // ?!?!
440 for (i = 0; i < depth; i++) {
441 b->buf[b->buf_used++] = '>';
442 }
sewardj738856f2009-07-15 14:48:32 +0000443 }
444
njnb1cc5d62010-07-06 04:05:23 +0000445 if (Vg_FailMsg == b->kind) {
446 // "valgrind: " prefix.
447 b->buf[b->buf_used++] = 'v';
448 b->buf[b->buf_used++] = 'a';
449 b->buf[b->buf_used++] = 'l';
450 b->buf[b->buf_used++] = 'g';
451 b->buf[b->buf_used++] = 'r';
452 b->buf[b->buf_used++] = 'i';
453 b->buf[b->buf_used++] = 'n';
454 b->buf[b->buf_used++] = 'd';
455 b->buf[b->buf_used++] = ':';
456 b->buf[b->buf_used++] = ' ';
457 } else {
458 switch (b->kind) {
459 case Vg_UserMsg: ch = '='; break;
460 case Vg_DebugMsg: ch = '-'; break;
njnb1cc5d62010-07-06 04:05:23 +0000461 case Vg_ClientMsg: ch = '*'; break;
462 default: ch = '?'; break;
463 }
sewardj738856f2009-07-15 14:48:32 +0000464
njnb1cc5d62010-07-06 04:05:23 +0000465 b->buf[b->buf_used++] = ch;
466 b->buf[b->buf_used++] = ch;
467
468 if (VG_(clo_time_stamp)) {
469 VG_(memset)(tmp, 0, sizeof(tmp));
470 VG_(elapsed_wallclock_time)(tmp);
471 tmp[sizeof(tmp)-1] = 0;
472 for (i = 0; tmp[i]; i++)
473 b->buf[b->buf_used++] = tmp[i];
474 }
475
476 VG_(sprintf)(tmp, "%d", VG_(getpid)());
sewardj738856f2009-07-15 14:48:32 +0000477 tmp[sizeof(tmp)-1] = 0;
478 for (i = 0; tmp[i]; i++)
479 b->buf[b->buf_used++] = tmp[i];
njnb1cc5d62010-07-06 04:05:23 +0000480
481 b->buf[b->buf_used++] = ch;
482 b->buf[b->buf_used++] = ch;
483 b->buf[b->buf_used++] = ' ';
sewardj738856f2009-07-15 14:48:32 +0000484 }
485
sewardj738856f2009-07-15 14:48:32 +0000486 /* We can't possibly have stuffed 96 chars in merely as a result
487 of making the preamble (can we?) */
488 vg_assert(b->buf_used < sizeof(b->buf)-32);
489 }
490
491 b->buf[b->buf_used++] = c;
492 b->buf[b->buf_used] = 0;
493
494 if (b->buf_used >= sizeof(b->buf) - 128) {
495 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
496 b->buf_used = 0;
497 }
498
499 b->atLeft = c == '\n';
500}
501
502
njnc44a6c22005-06-03 13:21:18 +0000503UInt VG_(vmessage) ( VgMsgKind kind, const HChar* format, va_list vargs )
504{
sewardj738856f2009-07-15 14:48:32 +0000505 UInt ret;
njnc44a6c22005-06-03 13:21:18 +0000506
sewardj738856f2009-07-15 14:48:32 +0000507 /* Note (carefully) that the buf persists from call to call, unlike
508 with the other printf variants in earlier parts of this file. */
509 vmessage_buf_t* b = &vmessage_buf; /* shorthand for convenience */
510
511 /* We have to set this each call, so that the correct flavour
512 of preamble is emitted at each \n. */
513 b->kind = kind;
514
sewardj738856f2009-07-15 14:48:32 +0000515 ret = VG_(debugLog_vprintf) ( add_to__vmessage_buf,
516 b, format, vargs );
njnc44a6c22005-06-03 13:21:18 +0000517
sewardj738856f2009-07-15 14:48:32 +0000518 /* If the message finished exactly with a \n, then flush it at this
519 point. If not, assume more bits of the same line will turn up
520 in later messages, so don't bother to flush it right now. */
521
522 if (b->atLeft && b->buf_used > 0) {
523 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
524 b->buf_used = 0;
njnc44a6c22005-06-03 13:21:18 +0000525 }
526
sewardj738856f2009-07-15 14:48:32 +0000527 return ret;
njnc44a6c22005-06-03 13:21:18 +0000528}
529
njnc44a6c22005-06-03 13:21:18 +0000530/* Send a simple single-part message. */
531UInt VG_(message) ( VgMsgKind kind, const HChar* format, ... )
532{
533 UInt count;
534 va_list vargs;
535 va_start(vargs,format);
536 count = VG_(vmessage) ( kind, format, vargs );
537 va_end(vargs);
538 return count;
539}
540
njnb1cc5d62010-07-06 04:05:23 +0000541static void revert_to_stderr ( void )
542{
543 VG_(log_output_sink).fd = 2; /* stderr */
544 VG_(log_output_sink).is_socket = False;
545}
546
sewardj738856f2009-07-15 14:48:32 +0000547/* VG_(message) variants with hardwired first argument. */
njnb1cc5d62010-07-06 04:05:23 +0000548
549UInt VG_(fmsg) ( const HChar* format, ... )
550{
551 UInt count;
552 va_list vargs;
553 va_start(vargs,format);
554 count = VG_(vmessage) ( Vg_FailMsg, format, vargs );
555 va_end(vargs);
556 return count;
557}
558
florianbbd9a212012-10-14 00:16:28 +0000559void VG_(fmsg_bad_option) ( const HChar* opt, const HChar* format, ... )
njnb1cc5d62010-07-06 04:05:23 +0000560{
561 va_list vargs;
562 va_start(vargs,format);
563 revert_to_stderr();
564 VG_(message) (Vg_FailMsg, "Bad option: %s\n", opt);
565 VG_(vmessage)(Vg_FailMsg, format, vargs );
566 VG_(message) (Vg_FailMsg, "Use --help for more information or consult the user manual.\n");
567 VG_(exit)(1);
568 va_end(vargs);
569}
570
sewardj738856f2009-07-15 14:48:32 +0000571UInt VG_(umsg) ( const HChar* format, ... )
572{
573 UInt count;
574 va_list vargs;
575 va_start(vargs,format);
576 count = VG_(vmessage) ( Vg_UserMsg, format, vargs );
577 va_end(vargs);
578 return count;
579}
580
581UInt VG_(dmsg) ( const HChar* format, ... )
582{
583 UInt count;
584 va_list vargs;
585 va_start(vargs,format);
586 count = VG_(vmessage) ( Vg_DebugMsg, format, vargs );
587 va_end(vargs);
588 return count;
589}
590
sewardj738856f2009-07-15 14:48:32 +0000591/* Flush any output that has accumulated in vmessage_buf as a
592 result of previous calls to VG_(message) et al. */
593void VG_(message_flush) ( void )
594{
595 vmessage_buf_t* b = &vmessage_buf;
596 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
597 b->buf_used = 0;
598}
599
njnb1cc5d62010-07-06 04:05:23 +0000600__attribute__((noreturn))
601void VG_(err_missing_prog) ( void )
602{
603 revert_to_stderr();
604 VG_(fmsg)("no program specified\n");
605 VG_(fmsg)("Use --help for more information.\n");
606 VG_(exit)(1);
607}
608
609__attribute__((noreturn))
florianbbd9a212012-10-14 00:16:28 +0000610void VG_(err_config_error) ( const HChar* format, ... )
njnb1cc5d62010-07-06 04:05:23 +0000611{
florian1763e812011-07-12 19:07:05 +0000612 va_list vargs;
613 va_start(vargs,format);
njnb1cc5d62010-07-06 04:05:23 +0000614 revert_to_stderr();
florian1763e812011-07-12 19:07:05 +0000615 VG_(message) (Vg_FailMsg, "Startup or configuration error:\n ");
616 VG_(vmessage)(Vg_FailMsg, format, vargs );
617 VG_(message) (Vg_FailMsg, "Unable to start up properly. Giving up.\n");
njnb1cc5d62010-07-06 04:05:23 +0000618 VG_(exit)(1);
florian1763e812011-07-12 19:07:05 +0000619 va_end(vargs);
njnb1cc5d62010-07-06 04:05:23 +0000620}
621
sewardj738856f2009-07-15 14:48:32 +0000622
njnc44a6c22005-06-03 13:21:18 +0000623/*--------------------------------------------------------------------*/
624/*--- end ---*/
625/*--------------------------------------------------------------------*/
626