blob: 13258568b5f00769d28564af58b90c7747dcb487 [file] [log] [blame]
florian12d2eb52014-10-30 22:17:56 +00001/* -*- mode: C; c-basic-offset: 3; -*- */
njnc44a6c22005-06-03 13:21:18 +00002
3/*--------------------------------------------------------------------*/
4/*--- Libc printing. m_libcprint.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
10
sewardj0f157dd2013-10-18 14:27:36 +000011 Copyright (C) 2000-2013 Julian Seward
njnc44a6c22005-06-03 13:21:18 +000012 jseward@acm.org
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file COPYING.
30*/
31
njnc7561b92005-06-19 01:24:32 +000032#include "pub_core_basics.h"
sewardj4cfea4f2006-10-14 19:26:10 +000033#include "pub_core_vki.h"
njnc44a6c22005-06-03 13:21:18 +000034#include "pub_core_debuglog.h"
florianc91f5842013-09-15 10:42:26 +000035#include "pub_core_gdbserver.h" // VG_(gdb_printf)
njnc44a6c22005-06-03 13:21:18 +000036#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000037#include "pub_core_libcassert.h"
sewardj592ae092005-11-08 19:01:44 +000038#include "pub_core_libcfile.h" // VG_(write)(), VG_(write_socket)()
njnc44a6c22005-06-03 13:21:18 +000039#include "pub_core_libcprint.h"
sewardj592ae092005-11-08 19:01:44 +000040#include "pub_core_libcproc.h" // VG_(getpid)(), VG_(read_millisecond_timer()
florian12d2eb52014-10-30 22:17:56 +000041#include "pub_core_mallocfree.h" // VG_(malloc)
njnc44a6c22005-06-03 13:21:18 +000042#include "pub_core_options.h"
florian1a046d52013-09-16 20:56:35 +000043#include "pub_core_clreq.h" // For RUNNING_ON_VALGRIND
njnc44a6c22005-06-03 13:21:18 +000044
njnc44a6c22005-06-03 13:21:18 +000045
46/* ---------------------------------------------------------------------
47 Writing to file or a socket
48 ------------------------------------------------------------------ */
49
sewardj738856f2009-07-15 14:48:32 +000050/* The destination sinks for normal and XML output. These have their
51 initial values here; they are set to final values by
52 m_main.main_process_cmd_line_options(). See comment at the top of
sewardj3b290482011-05-06 21:02:55 +000053 that function for the associated logic.
54 After startup, the gdbserver monitor command might temporarily
55 set the fd of log_output_sink to -2 to indicate that output is
56 to be given to gdb rather than output to the startup fd */
sewardj738856f2009-07-15 14:48:32 +000057OutputSink VG_(log_output_sink) = { 2, False }; /* 2 = stderr */
58OutputSink VG_(xml_output_sink) = { -1, False }; /* disabled */
59
njnc44a6c22005-06-03 13:21:18 +000060/* Do the low-level send of a message to the logging sink. */
sewardj738856f2009-07-15 14:48:32 +000061static
floriandbb35842012-10-27 18:39:11 +000062void send_bytes_to_logging_sink ( OutputSink* sink, const HChar* msg, Int nbytes )
njnc44a6c22005-06-03 13:21:18 +000063{
sewardj738856f2009-07-15 14:48:32 +000064 if (sink->is_socket) {
65 Int rc = VG_(write_socket)( sink->fd, msg, nbytes );
66 if (rc == -1) {
67 // For example, the listener process died. Switch back to stderr.
68 sink->is_socket = False;
69 sink->fd = 2;
70 VG_(write)( sink->fd, msg, nbytes );
71 }
72 } else {
73 /* sink->fd could have been set to -1 in the various
sewardj6e31f802007-11-17 22:29:25 +000074 sys-wrappers for sys_fork, if --child-silent-after-fork=yes
75 is in effect. That is a signal that we should not produce
76 any more output. */
sewardj738856f2009-07-15 14:48:32 +000077 if (sink->fd >= 0)
78 VG_(write)( sink->fd, msg, nbytes );
philippe02ea4132013-09-04 21:42:43 +000079 else if (sink->fd == -2 && nbytes > 0)
80 /* send to gdb the provided data, which must be
81 a null terminated string with len >= 1 */
sewardj3b290482011-05-06 21:02:55 +000082 VG_(gdb_printf)("%s", msg);
njnc44a6c22005-06-03 13:21:18 +000083 }
84}
85
sewardj738856f2009-07-15 14:48:32 +000086
njnc44a6c22005-06-03 13:21:18 +000087/* ---------------------------------------------------------------------
88 printf() and friends
89 ------------------------------------------------------------------ */
90
sewardj738856f2009-07-15 14:48:32 +000091/* --------- printf --------- */
92
sewardj45f4e7c2005-09-27 19:20:21 +000093typedef
94 struct {
sewardj738856f2009-07-15 14:48:32 +000095 HChar buf[512];
96 Int buf_used;
97 OutputSink* sink;
sewardj45f4e7c2005-09-27 19:20:21 +000098 }
sewardj738856f2009-07-15 14:48:32 +000099 printf_buf_t;
bart1a0cb6a2008-04-14 16:35:32 +0000100
njnc44a6c22005-06-03 13:21:18 +0000101// Adds a single char to the buffer. When the buffer gets sufficiently
102// full, we write its contents to the logging sink.
sewardj738856f2009-07-15 14:48:32 +0000103static void add_to__printf_buf ( HChar c, void *p )
njnc44a6c22005-06-03 13:21:18 +0000104{
sewardj738856f2009-07-15 14:48:32 +0000105 printf_buf_t *b = (printf_buf_t *)p;
njnc44a6c22005-06-03 13:21:18 +0000106
sewardj738856f2009-07-15 14:48:32 +0000107 if (b->buf_used > sizeof(b->buf) - 2 ) {
108 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
109 b->buf_used = 0;
njnc44a6c22005-06-03 13:21:18 +0000110 }
sewardj738856f2009-07-15 14:48:32 +0000111 b->buf[b->buf_used++] = c;
112 b->buf[b->buf_used] = 0;
floriane2800c92014-09-15 20:57:45 +0000113 vg_assert(b->buf_used < sizeof(b->buf));
sewardj738856f2009-07-15 14:48:32 +0000114}
115
116static UInt vprintf_to_buf ( printf_buf_t* b,
117 const HChar *format, va_list vargs )
118{
119 UInt ret = 0;
sewardj3b290482011-05-06 21:02:55 +0000120 if (b->sink->fd >= 0 || b->sink->fd == -2) {
sewardj738856f2009-07-15 14:48:32 +0000121 ret = VG_(debugLog_vprintf)
122 ( add_to__printf_buf, b, format, vargs );
123 }
124 return ret;
125}
126
127static UInt vprintf_WRK ( OutputSink* sink,
128 const HChar *format, va_list vargs )
129{
130 printf_buf_t myprintf_buf
131 = { "", 0, sink };
132 UInt ret
133 = vprintf_to_buf(&myprintf_buf, format, vargs);
134 // Write out any chars left in the buffer.
135 if (myprintf_buf.buf_used > 0) {
136 send_bytes_to_logging_sink( myprintf_buf.sink,
137 myprintf_buf.buf,
138 myprintf_buf.buf_used );
139 }
140 return ret;
njnc44a6c22005-06-03 13:21:18 +0000141}
142
143UInt VG_(vprintf) ( const HChar *format, va_list vargs )
144{
sewardj738856f2009-07-15 14:48:32 +0000145 return vprintf_WRK( &VG_(log_output_sink), format, vargs );
njnc44a6c22005-06-03 13:21:18 +0000146}
147
148UInt VG_(printf) ( const HChar *format, ... )
149{
150 UInt ret;
151 va_list vargs;
njnc44a6c22005-06-03 13:21:18 +0000152 va_start(vargs, format);
153 ret = VG_(vprintf)(format, vargs);
154 va_end(vargs);
njnc44a6c22005-06-03 13:21:18 +0000155 return ret;
156}
157
sewardj738856f2009-07-15 14:48:32 +0000158UInt VG_(vprintf_xml) ( const HChar *format, va_list vargs )
159{
160 return vprintf_WRK( &VG_(xml_output_sink), format, vargs );
161}
162
163UInt VG_(printf_xml) ( const HChar *format, ... )
bart1a0cb6a2008-04-14 16:35:32 +0000164{
165 UInt ret;
166 va_list vargs;
bart1a0cb6a2008-04-14 16:35:32 +0000167 va_start(vargs, format);
sewardj738856f2009-07-15 14:48:32 +0000168 ret = VG_(vprintf_xml)(format, vargs);
bart1a0cb6a2008-04-14 16:35:32 +0000169 va_end(vargs);
bart1a0cb6a2008-04-14 16:35:32 +0000170 return ret;
171}
172
philippe07c08522014-05-14 20:39:27 +0000173static UInt emit_WRK ( const HChar* format, va_list vargs )
174{
175 if (VG_(clo_xml)) {
176 return VG_(vprintf_xml)(format, vargs);
177 } else if (VG_(log_output_sink).fd == -2) {
178 return VG_(vprintf) (format, vargs);
179 } else {
180 return VG_(vmessage)(Vg_UserMsg, format, vargs);
181 }
182}
183UInt VG_(emit) ( const HChar* format, ... )
184{
185 UInt ret;
186 va_list vargs;
187 va_start(vargs, format);
188 ret = emit_WRK(format, vargs);
189 va_end(vargs);
190 return ret;
191}
sewardj738856f2009-07-15 14:48:32 +0000192
193/* --------- sprintf --------- */
194
195/* If we had an explicit buf structure here, it would contain only one
196 field, indicating where the next char is to go. So use p directly
197 for that, rather than having it be a pointer to a structure. */
198
199static void add_to__sprintf_buf ( HChar c, void *p )
200{
201 HChar** b = p;
202 *(*b)++ = c;
njnc44a6c22005-06-03 13:21:18 +0000203}
204
floriandbb35842012-10-27 18:39:11 +0000205UInt VG_(vsprintf) ( HChar* buf, const HChar *format, va_list vargs )
njnc44a6c22005-06-03 13:21:18 +0000206{
207 Int ret;
sewardj738856f2009-07-15 14:48:32 +0000208 HChar* sprintf_ptr = buf;
njnc44a6c22005-06-03 13:21:18 +0000209
210 ret = VG_(debugLog_vprintf)
sewardj738856f2009-07-15 14:48:32 +0000211 ( add_to__sprintf_buf, &sprintf_ptr, format, vargs );
212 add_to__sprintf_buf('\0', &sprintf_ptr);
njnc44a6c22005-06-03 13:21:18 +0000213
214 vg_assert(VG_(strlen)(buf) == ret);
215
216 return ret;
217}
218
floriandbb35842012-10-27 18:39:11 +0000219UInt VG_(sprintf) ( HChar* buf, const HChar *format, ... )
njnc44a6c22005-06-03 13:21:18 +0000220{
221 UInt ret;
222 va_list vargs;
njnc44a6c22005-06-03 13:21:18 +0000223 va_start(vargs,format);
224 ret = VG_(vsprintf)(buf, format, vargs);
225 va_end(vargs);
njnc44a6c22005-06-03 13:21:18 +0000226 return ret;
227}
228
sewardj45f4e7c2005-09-27 19:20:21 +0000229
sewardj738856f2009-07-15 14:48:32 +0000230/* --------- snprintf --------- */
231
florian3e81b8b2014-10-07 14:28:52 +0000232/* The return value of VG_(snprintf) and VG_(vsnprintf) differs from
233 what is defined in C99. Let S be the size of the buffer as given in
234 the 2nd argument.
235 Return value R:
236 R < S: The output string was successfully written to the buffer.
237 It is null-terminated and R == strlen( output string )
238 R == S: The supplied buffer was too small to hold the output string.
239 The first S-1 characters of the output string were written
240 to the buffer followed by the terminating null character.
241*/
242
sewardj45f4e7c2005-09-27 19:20:21 +0000243typedef
244 struct {
245 HChar* buf;
246 Int buf_size;
247 Int buf_used;
248 }
sewardj738856f2009-07-15 14:48:32 +0000249 snprintf_buf_t;
sewardj45f4e7c2005-09-27 19:20:21 +0000250
sewardj738856f2009-07-15 14:48:32 +0000251static void add_to__snprintf_buf ( HChar c, void* p )
sewardj45f4e7c2005-09-27 19:20:21 +0000252{
sewardj738856f2009-07-15 14:48:32 +0000253 snprintf_buf_t* b = p;
sewardj45f4e7c2005-09-27 19:20:21 +0000254 if (b->buf_size > 0 && b->buf_used < b->buf_size) {
255 b->buf[b->buf_used++] = c;
256 if (b->buf_used < b->buf_size)
257 b->buf[b->buf_used] = 0;
sewardj03e2bb82006-12-24 03:02:18 +0000258 else
259 b->buf[b->buf_size-1] = 0; /* pre: b->buf_size > 0 */
sewardj45f4e7c2005-09-27 19:20:21 +0000260 }
261}
262
floriandbb35842012-10-27 18:39:11 +0000263UInt VG_(vsnprintf) ( HChar* buf, Int size, const HChar *format, va_list vargs )
sewardj45f4e7c2005-09-27 19:20:21 +0000264{
sewardj738856f2009-07-15 14:48:32 +0000265 snprintf_buf_t b;
sewardj45f4e7c2005-09-27 19:20:21 +0000266 b.buf = buf;
267 b.buf_size = size < 0 ? 0 : size;
268 b.buf_used = 0;
philippe3a00f522013-02-26 21:54:28 +0000269 if (b.buf_size > 0)
270 b.buf[0] = 0; // ensure to null terminate buf if empty format
sewardjc7ffc942011-03-28 16:26:42 +0000271 (void) VG_(debugLog_vprintf)
272 ( add_to__snprintf_buf, &b, format, vargs );
sewardj45f4e7c2005-09-27 19:20:21 +0000273
274 return b.buf_used;
275}
276
floriandbb35842012-10-27 18:39:11 +0000277UInt VG_(snprintf) ( HChar* buf, Int size, const HChar *format, ... )
sewardj45f4e7c2005-09-27 19:20:21 +0000278{
279 UInt ret;
280 va_list vargs;
sewardj45f4e7c2005-09-27 19:20:21 +0000281 va_start(vargs,format);
282 ret = VG_(vsnprintf)(buf, size, format, vargs);
283 va_end(vargs);
sewardj45f4e7c2005-09-27 19:20:21 +0000284 return ret;
285}
286
287
sewardj738856f2009-07-15 14:48:32 +0000288/* --------- vcbprintf --------- */
289
290void VG_(vcbprintf)( void(*char_sink)(HChar, void* opaque),
291 void* opaque,
292 const HChar* format, va_list vargs )
293{
294 (void) VG_(debugLog_vprintf)
295 ( char_sink, opaque, format, vargs );
296}
297
298
florian12d2eb52014-10-30 22:17:56 +0000299/* --------- fprintf ---------- */
300
301/* This is like [v]fprintf, except it writes to a file handle using
302 VG_(write). */
303
304#define VGFILE_BUFSIZE 8192
305
306struct _VgFile {
307 HChar buf[VGFILE_BUFSIZE];
308 UInt num_chars; // number of characters in buf
309 Int fd; // file descriptor to write to
310};
311
312
313static void add_to__vgfile ( HChar c, void *p )
314{
315 VgFile *fp = p;
316
317 fp->buf[fp->num_chars++] = c;
318
319 if (fp->num_chars == VGFILE_BUFSIZE) {
320 VG_(write)(fp->fd, fp->buf, fp->num_chars);
321 fp->num_chars = 0;
322 }
323}
324
325VgFile *VG_(fopen)(const HChar *name, Int flags, Int mode)
326{
327 SysRes res = VG_(open)(name, flags, mode);
328
329 if (sr_isError(res))
330 return NULL;
331
332 VgFile *fp = VG_(malloc)("fopen", sizeof(VgFile));
333
334 fp->fd = sr_Res(res);
335 fp->num_chars = 0;
336
337 return fp;
338}
339
340
341UInt VG_(vfprintf) ( VgFile *fp, const HChar *format, va_list vargs )
342{
343 return VG_(debugLog_vprintf)(add_to__vgfile, fp, format, vargs);
344}
345
346UInt VG_(fprintf) ( VgFile *fp, const HChar *format, ... )
347{
348 UInt ret;
349 va_list vargs;
350 va_start(vargs,format);
351 ret = VG_(vfprintf)(fp, format, vargs);
352 va_end(vargs);
353 return ret;
354}
355
356void VG_(fclose)( VgFile *fp )
357{
358 // Flush the buffer.
359 if (fp->num_chars)
360 VG_(write)(fp->fd, fp->buf, fp->num_chars);
361
362 VG_(free)(fp);
363}
364
njnc44a6c22005-06-03 13:21:18 +0000365/* ---------------------------------------------------------------------
njn856c54e2005-06-26 18:43:40 +0000366 percentify()
367 ------------------------------------------------------------------ */
368
njn7a5915e2005-07-17 16:12:59 +0000369// Percentify n/m with d decimal places. Includes the '%' symbol at the end.
njn5eaff2f2005-09-25 19:11:45 +0000370// Right justifies in 'buf'.
floriandbb35842012-10-27 18:39:11 +0000371void VG_(percentify)(ULong n, ULong m, UInt d, Int n_buf, HChar buf[])
njn856c54e2005-06-26 18:43:40 +0000372{
373 Int i, len, space;
njn641e6162005-07-17 16:16:41 +0000374 ULong p1;
florian35a82d22014-10-14 21:47:43 +0000375 HChar fmt[32]; // large enough
njn856c54e2005-06-26 18:43:40 +0000376
njn641e6162005-07-17 16:16:41 +0000377 if (m == 0) {
njn5eaff2f2005-09-25 19:11:45 +0000378 // Have to generate the format string in order to be flexible about
379 // the width of the field.
florian35a82d22014-10-14 21:47:43 +0000380 VG_(sprintf)(fmt, "%%%ds", n_buf);
njn5eaff2f2005-09-25 19:11:45 +0000381 // fmt is now "%<n_buf>s" where <d> is 1,2,3...
382 VG_(sprintf)(buf, fmt, "--%");
njn641e6162005-07-17 16:16:41 +0000383 return;
384 }
385
386 p1 = (100*n) / m;
njn856c54e2005-06-26 18:43:40 +0000387
388 if (d == 0) {
florian35a82d22014-10-14 21:47:43 +0000389 VG_(sprintf)(buf, "%llu%%", p1); // FIXME: unsafe
njn856c54e2005-06-26 18:43:40 +0000390 } else {
391 ULong p2;
392 UInt ex;
njn856c54e2005-06-26 18:43:40 +0000393 switch (d) {
394 case 1: ex = 10; break;
395 case 2: ex = 100; break;
396 case 3: ex = 1000; break;
floriana4ca4fe2014-09-16 09:28:12 +0000397 default: VG_(core_panic)("Currently can only handle 3 decimal places");
njn856c54e2005-06-26 18:43:40 +0000398 }
399 p2 = ((100*n*ex) / m) % ex;
400 // Have to generate the format string in order to be flexible about
401 // the width of the post-decimal-point part.
florian35a82d22014-10-14 21:47:43 +0000402 VG_(sprintf)(fmt, "%%llu.%%0%ullu%%%%", d);
403 // fmt is now "%llu.%0<d>llu%%" where <d> is 1,2,3...
404 VG_(sprintf)(buf, fmt, p1, p2); // FIXME: unsafe
njn856c54e2005-06-26 18:43:40 +0000405 }
406
407 len = VG_(strlen)(buf);
408 space = n_buf - len;
409 if (space < 0) space = 0; /* Allow for v. small field_width */
410 i = len;
411
412 /* Right justify in field */
413 for ( ; i >= 0; i--) buf[i + space] = buf[i];
414 for (i = 0; i < space; i++) buf[i] = ' ';
415}
416
sewardja11553a2005-07-19 12:17:05 +0000417
418/* ---------------------------------------------------------------------
sewardj592ae092005-11-08 19:01:44 +0000419 elapsed_wallclock_time()
sewardja11553a2005-07-19 12:17:05 +0000420 ------------------------------------------------------------------ */
421
sewardj592ae092005-11-08 19:01:44 +0000422/* Get the elapsed wallclock time since startup into buf, which must
423 16 chars long. This is unchecked. It also relies on the
424 millisecond timer having been set to zero by an initial read in
425 m_main during startup. */
sewardja11553a2005-07-19 12:17:05 +0000426
florian77dec3a2014-11-14 22:34:40 +0000427void VG_(elapsed_wallclock_time) ( /*OUT*/HChar* buf, SizeT bufsize )
sewardja11553a2005-07-19 12:17:05 +0000428{
sewardj592ae092005-11-08 19:01:44 +0000429 UInt t, ms, s, mins, hours, days;
430
florian77dec3a2014-11-14 22:34:40 +0000431 vg_assert(bufsize > 20);
432
sewardj592ae092005-11-08 19:01:44 +0000433 t = VG_(read_millisecond_timer)(); /* milliseconds */
434
435 ms = t % 1000;
436 t /= 1000; /* now in seconds */
437
438 s = t % 60;
439 t /= 60; /* now in minutes */
440
441 mins = t % 60;
442 t /= 60; /* now in hours */
443
444 hours = t % 24;
445 t /= 24; /* now in days */
446
447 days = t;
448
njn82baca72009-07-24 05:35:49 +0000449 VG_(sprintf)(buf, "%02u:%02u:%02u:%02u.%03u ", days, hours, mins, s, ms);
sewardja11553a2005-07-19 12:17:05 +0000450}
451
452
njn856c54e2005-06-26 18:43:40 +0000453/* ---------------------------------------------------------------------
njnc44a6c22005-06-03 13:21:18 +0000454 message()
455 ------------------------------------------------------------------ */
456
sewardj738856f2009-07-15 14:48:32 +0000457/* A buffer for accumulating VG_(message) style output. This is
458 pretty much the same as VG_(printf)'s scheme, with two differences:
459
460 * The message buffer persists between calls, so that multiple
461 calls to VG_(message) can build up output.
462
463 * Whenever the first character on a line is emitted, the
464 ==PID== style preamble is stuffed in before it.
465*/
466typedef
467 struct {
468 HChar buf[512+128];
469 Int buf_used;
470 Bool atLeft; /* notionally, is the next char position at the
471 leftmost column? */
472 /* Current message kind - changes from call to call */
473 VgMsgKind kind;
sewardj738856f2009-07-15 14:48:32 +0000474 /* destination */
475 OutputSink* sink;
476 }
477 vmessage_buf_t;
478
479static vmessage_buf_t vmessage_buf
sewardj8ddb93a2010-02-15 10:07:05 +0000480 = { "", 0, True, Vg_UserMsg, &VG_(log_output_sink) };
sewardj738856f2009-07-15 14:48:32 +0000481
482
483// Adds a single char to the buffer. We aim to have at least 128
484// bytes free in the buffer, so that it's always possible to emit
485// the preamble into the buffer if c happens to be the character
486// following a \n. When the buffer gets too full, we write its
487// contents to the logging sink.
488static void add_to__vmessage_buf ( HChar c, void *p )
489{
490 HChar tmp[64];
491 vmessage_buf_t* b = (vmessage_buf_t*)p;
492
493 vg_assert(b->buf_used >= 0 && b->buf_used < sizeof(b->buf)-128);
494
495 if (UNLIKELY(b->atLeft)) {
496 // insert preamble
497 HChar ch;
498 Int i, depth;
499
sewardj738856f2009-07-15 14:48:32 +0000500 // Print one '>' in front of the messages for each level of
501 // self-hosting being performed.
philippe72faf102012-03-11 22:24:03 +0000502 // Do not print such '>' if sim hint "no-inner-prefix" given
503 // (useful to run regression tests in an outer/inner setup
504 // and avoid the diff failing due to these unexpected '>').
sewardj738856f2009-07-15 14:48:32 +0000505 depth = RUNNING_ON_VALGRIND;
philippeec905f72014-08-17 20:03:51 +0000506 if (depth > 0
507 && !SimHintiS(SimHint_no_inner_prefix, VG_(clo_sim_hints))) {
philippe72faf102012-03-11 22:24:03 +0000508 if (depth > 10)
509 depth = 10; // ?!?!
510 for (i = 0; i < depth; i++) {
511 b->buf[b->buf_used++] = '>';
512 }
sewardj738856f2009-07-15 14:48:32 +0000513 }
514
njnb1cc5d62010-07-06 04:05:23 +0000515 if (Vg_FailMsg == b->kind) {
516 // "valgrind: " prefix.
517 b->buf[b->buf_used++] = 'v';
518 b->buf[b->buf_used++] = 'a';
519 b->buf[b->buf_used++] = 'l';
520 b->buf[b->buf_used++] = 'g';
521 b->buf[b->buf_used++] = 'r';
522 b->buf[b->buf_used++] = 'i';
523 b->buf[b->buf_used++] = 'n';
524 b->buf[b->buf_used++] = 'd';
525 b->buf[b->buf_used++] = ':';
526 b->buf[b->buf_used++] = ' ';
527 } else {
528 switch (b->kind) {
529 case Vg_UserMsg: ch = '='; break;
530 case Vg_DebugMsg: ch = '-'; break;
njnb1cc5d62010-07-06 04:05:23 +0000531 case Vg_ClientMsg: ch = '*'; break;
532 default: ch = '?'; break;
533 }
sewardj738856f2009-07-15 14:48:32 +0000534
njnb1cc5d62010-07-06 04:05:23 +0000535 b->buf[b->buf_used++] = ch;
536 b->buf[b->buf_used++] = ch;
537
538 if (VG_(clo_time_stamp)) {
florian77dec3a2014-11-14 22:34:40 +0000539 VG_(elapsed_wallclock_time)(tmp, sizeof tmp);
njnb1cc5d62010-07-06 04:05:23 +0000540 for (i = 0; tmp[i]; i++)
541 b->buf[b->buf_used++] = tmp[i];
542 }
543
544 VG_(sprintf)(tmp, "%d", VG_(getpid)());
sewardj738856f2009-07-15 14:48:32 +0000545 tmp[sizeof(tmp)-1] = 0;
546 for (i = 0; tmp[i]; i++)
547 b->buf[b->buf_used++] = tmp[i];
njnb1cc5d62010-07-06 04:05:23 +0000548
549 b->buf[b->buf_used++] = ch;
550 b->buf[b->buf_used++] = ch;
551 b->buf[b->buf_used++] = ' ';
sewardj738856f2009-07-15 14:48:32 +0000552 }
553
sewardj738856f2009-07-15 14:48:32 +0000554 /* We can't possibly have stuffed 96 chars in merely as a result
555 of making the preamble (can we?) */
556 vg_assert(b->buf_used < sizeof(b->buf)-32);
557 }
558
559 b->buf[b->buf_used++] = c;
560 b->buf[b->buf_used] = 0;
561
562 if (b->buf_used >= sizeof(b->buf) - 128) {
563 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
564 b->buf_used = 0;
565 }
566
567 b->atLeft = c == '\n';
568}
569
570
njnc44a6c22005-06-03 13:21:18 +0000571UInt VG_(vmessage) ( VgMsgKind kind, const HChar* format, va_list vargs )
572{
sewardj738856f2009-07-15 14:48:32 +0000573 UInt ret;
njnc44a6c22005-06-03 13:21:18 +0000574
sewardj738856f2009-07-15 14:48:32 +0000575 /* Note (carefully) that the buf persists from call to call, unlike
576 with the other printf variants in earlier parts of this file. */
577 vmessage_buf_t* b = &vmessage_buf; /* shorthand for convenience */
578
579 /* We have to set this each call, so that the correct flavour
580 of preamble is emitted at each \n. */
581 b->kind = kind;
582
sewardj738856f2009-07-15 14:48:32 +0000583 ret = VG_(debugLog_vprintf) ( add_to__vmessage_buf,
584 b, format, vargs );
njnc44a6c22005-06-03 13:21:18 +0000585
sewardj738856f2009-07-15 14:48:32 +0000586 /* If the message finished exactly with a \n, then flush it at this
587 point. If not, assume more bits of the same line will turn up
588 in later messages, so don't bother to flush it right now. */
589
590 if (b->atLeft && b->buf_used > 0) {
591 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
592 b->buf_used = 0;
njnc44a6c22005-06-03 13:21:18 +0000593 }
594
sewardj738856f2009-07-15 14:48:32 +0000595 return ret;
njnc44a6c22005-06-03 13:21:18 +0000596}
597
njnc44a6c22005-06-03 13:21:18 +0000598/* Send a simple single-part message. */
599UInt VG_(message) ( VgMsgKind kind, const HChar* format, ... )
600{
601 UInt count;
602 va_list vargs;
603 va_start(vargs,format);
604 count = VG_(vmessage) ( kind, format, vargs );
605 va_end(vargs);
606 return count;
607}
608
njnb1cc5d62010-07-06 04:05:23 +0000609static void revert_to_stderr ( void )
610{
611 VG_(log_output_sink).fd = 2; /* stderr */
612 VG_(log_output_sink).is_socket = False;
613}
614
sewardj738856f2009-07-15 14:48:32 +0000615/* VG_(message) variants with hardwired first argument. */
njnb1cc5d62010-07-06 04:05:23 +0000616
617UInt VG_(fmsg) ( const HChar* format, ... )
618{
619 UInt count;
620 va_list vargs;
621 va_start(vargs,format);
622 count = VG_(vmessage) ( Vg_FailMsg, format, vargs );
623 va_end(vargs);
624 return count;
625}
626
florianbbd9a212012-10-14 00:16:28 +0000627void VG_(fmsg_bad_option) ( const HChar* opt, const HChar* format, ... )
njnb1cc5d62010-07-06 04:05:23 +0000628{
629 va_list vargs;
630 va_start(vargs,format);
631 revert_to_stderr();
632 VG_(message) (Vg_FailMsg, "Bad option: %s\n", opt);
633 VG_(vmessage)(Vg_FailMsg, format, vargs );
634 VG_(message) (Vg_FailMsg, "Use --help for more information or consult the user manual.\n");
njnb1cc5d62010-07-06 04:05:23 +0000635 va_end(vargs);
florianbe1036e2014-10-17 19:44:55 +0000636 VG_(exit)(1);
njnb1cc5d62010-07-06 04:05:23 +0000637}
638
sewardj738856f2009-07-15 14:48:32 +0000639UInt VG_(umsg) ( const HChar* format, ... )
640{
641 UInt count;
642 va_list vargs;
643 va_start(vargs,format);
644 count = VG_(vmessage) ( Vg_UserMsg, format, vargs );
645 va_end(vargs);
646 return count;
647}
648
649UInt VG_(dmsg) ( const HChar* format, ... )
650{
651 UInt count;
652 va_list vargs;
653 va_start(vargs,format);
654 count = VG_(vmessage) ( Vg_DebugMsg, format, vargs );
655 va_end(vargs);
656 return count;
657}
658
sewardj738856f2009-07-15 14:48:32 +0000659/* Flush any output that has accumulated in vmessage_buf as a
660 result of previous calls to VG_(message) et al. */
661void VG_(message_flush) ( void )
662{
663 vmessage_buf_t* b = &vmessage_buf;
664 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
665 b->buf_used = 0;
666}
667
njnb1cc5d62010-07-06 04:05:23 +0000668__attribute__((noreturn))
669void VG_(err_missing_prog) ( void )
670{
671 revert_to_stderr();
672 VG_(fmsg)("no program specified\n");
673 VG_(fmsg)("Use --help for more information.\n");
674 VG_(exit)(1);
675}
676
677__attribute__((noreturn))
florianbbd9a212012-10-14 00:16:28 +0000678void VG_(err_config_error) ( const HChar* format, ... )
njnb1cc5d62010-07-06 04:05:23 +0000679{
florian1763e812011-07-12 19:07:05 +0000680 va_list vargs;
681 va_start(vargs,format);
njnb1cc5d62010-07-06 04:05:23 +0000682 revert_to_stderr();
florian1763e812011-07-12 19:07:05 +0000683 VG_(message) (Vg_FailMsg, "Startup or configuration error:\n ");
684 VG_(vmessage)(Vg_FailMsg, format, vargs );
685 VG_(message) (Vg_FailMsg, "Unable to start up properly. Giving up.\n");
florian1763e812011-07-12 19:07:05 +0000686 va_end(vargs);
florianbe1036e2014-10-17 19:44:55 +0000687 VG_(exit)(1);
njnb1cc5d62010-07-06 04:05:23 +0000688}
689
sewardj738856f2009-07-15 14:48:32 +0000690
njnc44a6c22005-06-03 13:21:18 +0000691/*--------------------------------------------------------------------*/
692/*--- end ---*/
693/*--------------------------------------------------------------------*/