1024598e40c84666cc311a42c256bbf880db3ac99sewardj
2024598e40c84666cc311a42c256bbf880db3ac99sewardj/* This demonstrates a stack overrun bug that exp-ptrcheck found while
3024598e40c84666cc311a42c256bbf880db3ac99sewardj   running Valgrind itself (self hosting).  As at 12 Sept 08 this bug
4024598e40c84666cc311a42c256bbf880db3ac99sewardj   is still in Valgrind. */
5024598e40c84666cc311a42c256bbf880db3ac99sewardj
6024598e40c84666cc311a42c256bbf880db3ac99sewardj#include <stdio.h>
7024598e40c84666cc311a42c256bbf880db3ac99sewardj#include <assert.h>
803ca90b84db7071c93455880cf0a14027655cbd9sewardj#include <stdarg.h>
9024598e40c84666cc311a42c256bbf880db3ac99sewardj
10024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef  unsigned long long int  ULong;
1103ca90b84db7071c93455880cf0a14027655cbd9sewardjtypedef    signed long long int  Long;
12024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef  unsigned int            UInt;
13024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef  signed int              Int;
1403ca90b84db7071c93455880cf0a14027655cbd9sewardjtypedef  signed char             Char;
1503ca90b84db7071c93455880cf0a14027655cbd9sewardjtypedef  char                    HChar;
1603ca90b84db7071c93455880cf0a14027655cbd9sewardjtypedef unsigned long            UWord;
1703ca90b84db7071c93455880cf0a14027655cbd9sewardjtypedef   signed long            Word;
1803ca90b84db7071c93455880cf0a14027655cbd9sewardj
1903ca90b84db7071c93455880cf0a14027655cbd9sewardj
2003ca90b84db7071c93455880cf0a14027655cbd9sewardj
2103ca90b84db7071c93455880cf0a14027655cbd9sewardjtypedef  unsigned char  Bool;
2203ca90b84db7071c93455880cf0a14027655cbd9sewardj#define  True   ((Bool)1)
2303ca90b84db7071c93455880cf0a14027655cbd9sewardj#define  False  ((Bool)0)
2403ca90b84db7071c93455880cf0a14027655cbd9sewardj
2503ca90b84db7071c93455880cf0a14027655cbd9sewardj#define VG_(_str) VG_##_str
2603ca90b84db7071c93455880cf0a14027655cbd9sewardj
2703ca90b84db7071c93455880cf0a14027655cbd9sewardj
2803ca90b84db7071c93455880cf0a14027655cbd9sewardj/* ---------------------------------------------------------------------
2903ca90b84db7071c93455880cf0a14027655cbd9sewardj   vg_sprintf, copied from m_libcprint.c
3003ca90b84db7071c93455880cf0a14027655cbd9sewardj   ------------------------------------------------------------------ */
3103ca90b84db7071c93455880cf0a14027655cbd9sewardjUInt
3203ca90b84db7071c93455880cf0a14027655cbd9sewardjVG_(debugLog_vprintf) (
3303ca90b84db7071c93455880cf0a14027655cbd9sewardj   void(*send)(HChar,void*),
3403ca90b84db7071c93455880cf0a14027655cbd9sewardj   void* send_arg2,
3503ca90b84db7071c93455880cf0a14027655cbd9sewardj   const HChar* format,
3603ca90b84db7071c93455880cf0a14027655cbd9sewardj   va_list vargs
3703ca90b84db7071c93455880cf0a14027655cbd9sewardj                        );
3803ca90b84db7071c93455880cf0a14027655cbd9sewardj
3903ca90b84db7071c93455880cf0a14027655cbd9sewardj/* ---------------------------------------------------------------------
4003ca90b84db7071c93455880cf0a14027655cbd9sewardj   printf() and friends
4103ca90b84db7071c93455880cf0a14027655cbd9sewardj   ------------------------------------------------------------------ */
4203ca90b84db7071c93455880cf0a14027655cbd9sewardjtypedef
4303ca90b84db7071c93455880cf0a14027655cbd9sewardj   struct { Int fd; Bool is_socket; }
4403ca90b84db7071c93455880cf0a14027655cbd9sewardj   OutputSink;
4503ca90b84db7071c93455880cf0a14027655cbd9sewardj
4603ca90b84db7071c93455880cf0a14027655cbd9sewardj
4703ca90b84db7071c93455880cf0a14027655cbd9sewardjOutputSink VG_(log_output_sink) = {  2, False }; /* 2 = stderr */
4803ca90b84db7071c93455880cf0a14027655cbd9sewardj
4903ca90b84db7071c93455880cf0a14027655cbd9sewardj/* Do the low-level send of a message to the logging sink. */
5003ca90b84db7071c93455880cf0a14027655cbd9sewardjstatic
5103ca90b84db7071c93455880cf0a14027655cbd9sewardjvoid send_bytes_to_logging_sink ( OutputSink* sink, HChar* msg, Int nbytes )
5203ca90b84db7071c93455880cf0a14027655cbd9sewardj{
5303ca90b84db7071c93455880cf0a14027655cbd9sewardj   fwrite(msg, 1, nbytes, stdout);
5403ca90b84db7071c93455880cf0a14027655cbd9sewardj   fflush(stdout);
5503ca90b84db7071c93455880cf0a14027655cbd9sewardj}
5603ca90b84db7071c93455880cf0a14027655cbd9sewardj
5703ca90b84db7071c93455880cf0a14027655cbd9sewardj
5803ca90b84db7071c93455880cf0a14027655cbd9sewardj/* --------- printf --------- */
5903ca90b84db7071c93455880cf0a14027655cbd9sewardj
6003ca90b84db7071c93455880cf0a14027655cbd9sewardjtypedef
6103ca90b84db7071c93455880cf0a14027655cbd9sewardj   struct {
6203ca90b84db7071c93455880cf0a14027655cbd9sewardj      HChar       buf[512];
6303ca90b84db7071c93455880cf0a14027655cbd9sewardj      Int         buf_used;
6403ca90b84db7071c93455880cf0a14027655cbd9sewardj      OutputSink* sink;
6503ca90b84db7071c93455880cf0a14027655cbd9sewardj   }
6603ca90b84db7071c93455880cf0a14027655cbd9sewardj   printf_buf_t;
6703ca90b84db7071c93455880cf0a14027655cbd9sewardj
6803ca90b84db7071c93455880cf0a14027655cbd9sewardj// Adds a single char to the buffer.  When the buffer gets sufficiently
6903ca90b84db7071c93455880cf0a14027655cbd9sewardj// full, we write its contents to the logging sink.
7003ca90b84db7071c93455880cf0a14027655cbd9sewardjstatic void add_to__printf_buf ( HChar c, void *p )
7103ca90b84db7071c93455880cf0a14027655cbd9sewardj{
7203ca90b84db7071c93455880cf0a14027655cbd9sewardj   printf_buf_t *b = (printf_buf_t *)p;
7303ca90b84db7071c93455880cf0a14027655cbd9sewardj
7403ca90b84db7071c93455880cf0a14027655cbd9sewardj   if (b->buf_used > sizeof(b->buf) - 2 ) {
7503ca90b84db7071c93455880cf0a14027655cbd9sewardj      send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
7603ca90b84db7071c93455880cf0a14027655cbd9sewardj      b->buf_used = 0;
7703ca90b84db7071c93455880cf0a14027655cbd9sewardj   }
7803ca90b84db7071c93455880cf0a14027655cbd9sewardj   b->buf[b->buf_used++] = c;
7903ca90b84db7071c93455880cf0a14027655cbd9sewardj   b->buf[b->buf_used]   = 0;
8003ca90b84db7071c93455880cf0a14027655cbd9sewardj   assert(b->buf_used < sizeof(b->buf));
8103ca90b84db7071c93455880cf0a14027655cbd9sewardj}
8203ca90b84db7071c93455880cf0a14027655cbd9sewardj
8303ca90b84db7071c93455880cf0a14027655cbd9sewardj__attribute__((noinline))
8403ca90b84db7071c93455880cf0a14027655cbd9sewardjstatic UInt vprintf_to_buf ( printf_buf_t* b,
8503ca90b84db7071c93455880cf0a14027655cbd9sewardj                             const HChar *format, va_list vargs )
8603ca90b84db7071c93455880cf0a14027655cbd9sewardj{
8703ca90b84db7071c93455880cf0a14027655cbd9sewardj   UInt ret = 0;
8803ca90b84db7071c93455880cf0a14027655cbd9sewardj   if (b->sink->fd >= 0 || b->sink->fd == -2) {
8903ca90b84db7071c93455880cf0a14027655cbd9sewardj      ret = VG_(debugLog_vprintf)
9003ca90b84db7071c93455880cf0a14027655cbd9sewardj               ( add_to__printf_buf, b, format, vargs );
9103ca90b84db7071c93455880cf0a14027655cbd9sewardj   }
9203ca90b84db7071c93455880cf0a14027655cbd9sewardj   return ret;
9303ca90b84db7071c93455880cf0a14027655cbd9sewardj}
9403ca90b84db7071c93455880cf0a14027655cbd9sewardj
9503ca90b84db7071c93455880cf0a14027655cbd9sewardj__attribute__((noinline))
9603ca90b84db7071c93455880cf0a14027655cbd9sewardjstatic UInt vprintf_WRK ( OutputSink* sink,
9703ca90b84db7071c93455880cf0a14027655cbd9sewardj                          const HChar *format, va_list vargs )
9803ca90b84db7071c93455880cf0a14027655cbd9sewardj{
9903ca90b84db7071c93455880cf0a14027655cbd9sewardj   printf_buf_t myprintf_buf
10003ca90b84db7071c93455880cf0a14027655cbd9sewardj      = { "", 0, sink };
101d1897e1b9b34cd457daa9c95fd25cf1cbcd8702bflorian   UInt ret;
102d1897e1b9b34cd457daa9c95fd25cf1cbcd8702bflorian   ret = vprintf_to_buf(&myprintf_buf, format, vargs);
10303ca90b84db7071c93455880cf0a14027655cbd9sewardj   // Write out any chars left in the buffer.
10403ca90b84db7071c93455880cf0a14027655cbd9sewardj   if (myprintf_buf.buf_used > 0) {
10503ca90b84db7071c93455880cf0a14027655cbd9sewardj      send_bytes_to_logging_sink( myprintf_buf.sink,
10603ca90b84db7071c93455880cf0a14027655cbd9sewardj                                  myprintf_buf.buf,
10703ca90b84db7071c93455880cf0a14027655cbd9sewardj                                  myprintf_buf.buf_used );
10803ca90b84db7071c93455880cf0a14027655cbd9sewardj   }
10903ca90b84db7071c93455880cf0a14027655cbd9sewardj   return ret;
11003ca90b84db7071c93455880cf0a14027655cbd9sewardj}
11103ca90b84db7071c93455880cf0a14027655cbd9sewardj
11203ca90b84db7071c93455880cf0a14027655cbd9sewardj__attribute__((noinline))
11303ca90b84db7071c93455880cf0a14027655cbd9sewardjUInt VG_(vprintf) ( const HChar *format, va_list vargs )
11403ca90b84db7071c93455880cf0a14027655cbd9sewardj{
11503ca90b84db7071c93455880cf0a14027655cbd9sewardj   return vprintf_WRK( &VG_(log_output_sink), format, vargs );
11603ca90b84db7071c93455880cf0a14027655cbd9sewardj}
11703ca90b84db7071c93455880cf0a14027655cbd9sewardj
11803ca90b84db7071c93455880cf0a14027655cbd9sewardj__attribute__((noinline))
11903ca90b84db7071c93455880cf0a14027655cbd9sewardjUInt VG_(printf) ( const HChar *format, ... )
12003ca90b84db7071c93455880cf0a14027655cbd9sewardj{
12103ca90b84db7071c93455880cf0a14027655cbd9sewardj   UInt ret;
12203ca90b84db7071c93455880cf0a14027655cbd9sewardj   va_list vargs;
12303ca90b84db7071c93455880cf0a14027655cbd9sewardj   va_start(vargs, format);
12403ca90b84db7071c93455880cf0a14027655cbd9sewardj   ret = VG_(vprintf)(format, vargs);
12503ca90b84db7071c93455880cf0a14027655cbd9sewardj   va_end(vargs);
12603ca90b84db7071c93455880cf0a14027655cbd9sewardj   return ret;
12703ca90b84db7071c93455880cf0a14027655cbd9sewardj}
12803ca90b84db7071c93455880cf0a14027655cbd9sewardj
12903ca90b84db7071c93455880cf0a14027655cbd9sewardjstatic Bool toBool ( Int x ) {
13003ca90b84db7071c93455880cf0a14027655cbd9sewardj   Int r = (x == 0) ? False : True;
13103ca90b84db7071c93455880cf0a14027655cbd9sewardj   return (Bool)r;
13203ca90b84db7071c93455880cf0a14027655cbd9sewardj}
13303ca90b84db7071c93455880cf0a14027655cbd9sewardj
13403ca90b84db7071c93455880cf0a14027655cbd9sewardj__attribute__((noinline))
13503ca90b84db7071c93455880cf0a14027655cbd9sewardjstatic Int local_strlen ( const HChar* str )
13603ca90b84db7071c93455880cf0a14027655cbd9sewardj{
13703ca90b84db7071c93455880cf0a14027655cbd9sewardj   Int i = 0;
13803ca90b84db7071c93455880cf0a14027655cbd9sewardj   while (str[i] != 0) i++;
13903ca90b84db7071c93455880cf0a14027655cbd9sewardj   return i;
14003ca90b84db7071c93455880cf0a14027655cbd9sewardj}
14103ca90b84db7071c93455880cf0a14027655cbd9sewardj
14203ca90b84db7071c93455880cf0a14027655cbd9sewardj__attribute__((noinline))
14303ca90b84db7071c93455880cf0a14027655cbd9sewardjstatic HChar local_toupper ( HChar c )
14403ca90b84db7071c93455880cf0a14027655cbd9sewardj{
14503ca90b84db7071c93455880cf0a14027655cbd9sewardj   if (c >= 'a' && c <= 'z')
14603ca90b84db7071c93455880cf0a14027655cbd9sewardj      return c + ('A' - 'a');
14703ca90b84db7071c93455880cf0a14027655cbd9sewardj   else
14803ca90b84db7071c93455880cf0a14027655cbd9sewardj      return c;
14903ca90b84db7071c93455880cf0a14027655cbd9sewardj}
15003ca90b84db7071c93455880cf0a14027655cbd9sewardj
15103ca90b84db7071c93455880cf0a14027655cbd9sewardj
15203ca90b84db7071c93455880cf0a14027655cbd9sewardj/*------------------------------------------------------------*/
15303ca90b84db7071c93455880cf0a14027655cbd9sewardj/*--- A simple, generic, vprintf implementation.           ---*/
15403ca90b84db7071c93455880cf0a14027655cbd9sewardj/*------------------------------------------------------------*/
15503ca90b84db7071c93455880cf0a14027655cbd9sewardj
15603ca90b84db7071c93455880cf0a14027655cbd9sewardj/* -----------------------------------------------
15703ca90b84db7071c93455880cf0a14027655cbd9sewardj   Distantly derived from:
15803ca90b84db7071c93455880cf0a14027655cbd9sewardj
15903ca90b84db7071c93455880cf0a14027655cbd9sewardj      vprintf replacement for Checker.
16003ca90b84db7071c93455880cf0a14027655cbd9sewardj      Copyright 1993, 1994, 1995 Tristan Gingold
16103ca90b84db7071c93455880cf0a14027655cbd9sewardj      Written September 1993 Tristan Gingold
16203ca90b84db7071c93455880cf0a14027655cbd9sewardj      Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
16303ca90b84db7071c93455880cf0a14027655cbd9sewardj
16403ca90b84db7071c93455880cf0a14027655cbd9sewardj   (Checker itself was GPL'd.)
16503ca90b84db7071c93455880cf0a14027655cbd9sewardj   ----------------------------------------------- */
16603ca90b84db7071c93455880cf0a14027655cbd9sewardj
16703ca90b84db7071c93455880cf0a14027655cbd9sewardj/* Some flags.  */
16803ca90b84db7071c93455880cf0a14027655cbd9sewardj#define VG_MSG_SIGNED    1 /* The value is signed. */
16903ca90b84db7071c93455880cf0a14027655cbd9sewardj#define VG_MSG_ZJUSTIFY  2 /* Must justify with '0'. */
17003ca90b84db7071c93455880cf0a14027655cbd9sewardj#define VG_MSG_LJUSTIFY  4 /* Must justify on the left. */
17103ca90b84db7071c93455880cf0a14027655cbd9sewardj#define VG_MSG_PAREN     8 /* Parenthesize if present (for %y) */
17203ca90b84db7071c93455880cf0a14027655cbd9sewardj#define VG_MSG_COMMA    16 /* Add commas to numbers (for %d, %u) */
17303ca90b84db7071c93455880cf0a14027655cbd9sewardj#define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
17403ca90b84db7071c93455880cf0a14027655cbd9sewardj
17503ca90b84db7071c93455880cf0a14027655cbd9sewardj/* Copy a string into the buffer. */
17603ca90b84db7071c93455880cf0a14027655cbd9sewardjstatic __attribute__((noinline))
17703ca90b84db7071c93455880cf0a14027655cbd9sewardjUInt myvprintf_str ( void(*send)(HChar,void*),
17803ca90b84db7071c93455880cf0a14027655cbd9sewardj                     void* send_arg2,
17903ca90b84db7071c93455880cf0a14027655cbd9sewardj                     Int flags,
18003ca90b84db7071c93455880cf0a14027655cbd9sewardj                     Int width,
18103ca90b84db7071c93455880cf0a14027655cbd9sewardj                     HChar* str,
18203ca90b84db7071c93455880cf0a14027655cbd9sewardj                     Bool capitalise )
18303ca90b84db7071c93455880cf0a14027655cbd9sewardj{
18403ca90b84db7071c93455880cf0a14027655cbd9sewardj#  define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
18503ca90b84db7071c93455880cf0a14027655cbd9sewardj   UInt ret = 0;
18603ca90b84db7071c93455880cf0a14027655cbd9sewardj   Int i, extra;
18703ca90b84db7071c93455880cf0a14027655cbd9sewardj   Int len = local_strlen(str);
18803ca90b84db7071c93455880cf0a14027655cbd9sewardj
18903ca90b84db7071c93455880cf0a14027655cbd9sewardj   if (width == 0) {
19003ca90b84db7071c93455880cf0a14027655cbd9sewardj      ret += len;
19103ca90b84db7071c93455880cf0a14027655cbd9sewardj      for (i = 0; i < len; i++)
19203ca90b84db7071c93455880cf0a14027655cbd9sewardj          send(MAYBE_TOUPPER(str[i]), send_arg2);
19303ca90b84db7071c93455880cf0a14027655cbd9sewardj      return ret;
19403ca90b84db7071c93455880cf0a14027655cbd9sewardj   }
19503ca90b84db7071c93455880cf0a14027655cbd9sewardj
19603ca90b84db7071c93455880cf0a14027655cbd9sewardj   if (len > width) {
19703ca90b84db7071c93455880cf0a14027655cbd9sewardj      ret += width;
19803ca90b84db7071c93455880cf0a14027655cbd9sewardj      for (i = 0; i < width; i++)
19903ca90b84db7071c93455880cf0a14027655cbd9sewardj         send(MAYBE_TOUPPER(str[i]), send_arg2);
20003ca90b84db7071c93455880cf0a14027655cbd9sewardj      return ret;
20103ca90b84db7071c93455880cf0a14027655cbd9sewardj   }
20203ca90b84db7071c93455880cf0a14027655cbd9sewardj
20303ca90b84db7071c93455880cf0a14027655cbd9sewardj   extra = width - len;
20403ca90b84db7071c93455880cf0a14027655cbd9sewardj   if (flags & VG_MSG_LJUSTIFY) {
20503ca90b84db7071c93455880cf0a14027655cbd9sewardj      ret += extra;
20603ca90b84db7071c93455880cf0a14027655cbd9sewardj      for (i = 0; i < extra; i++)
20703ca90b84db7071c93455880cf0a14027655cbd9sewardj         send(' ', send_arg2);
20803ca90b84db7071c93455880cf0a14027655cbd9sewardj   }
20903ca90b84db7071c93455880cf0a14027655cbd9sewardj   ret += len;
21003ca90b84db7071c93455880cf0a14027655cbd9sewardj   for (i = 0; i < len; i++)
21103ca90b84db7071c93455880cf0a14027655cbd9sewardj      send(MAYBE_TOUPPER(str[i]), send_arg2);
21203ca90b84db7071c93455880cf0a14027655cbd9sewardj   if (!(flags & VG_MSG_LJUSTIFY)) {
21303ca90b84db7071c93455880cf0a14027655cbd9sewardj      ret += extra;
21403ca90b84db7071c93455880cf0a14027655cbd9sewardj      for (i = 0; i < extra; i++)
21503ca90b84db7071c93455880cf0a14027655cbd9sewardj         send(' ', send_arg2);
21603ca90b84db7071c93455880cf0a14027655cbd9sewardj   }
21703ca90b84db7071c93455880cf0a14027655cbd9sewardj
21803ca90b84db7071c93455880cf0a14027655cbd9sewardj#  undef MAYBE_TOUPPER
21903ca90b84db7071c93455880cf0a14027655cbd9sewardj   return ret;
22003ca90b84db7071c93455880cf0a14027655cbd9sewardj}
22103ca90b84db7071c93455880cf0a14027655cbd9sewardj
22203ca90b84db7071c93455880cf0a14027655cbd9sewardj
22303ca90b84db7071c93455880cf0a14027655cbd9sewardj/* Copy a string into the buffer, escaping bad XML chars. */
22403ca90b84db7071c93455880cf0a14027655cbd9sewardjstatic
22503ca90b84db7071c93455880cf0a14027655cbd9sewardjUInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
22603ca90b84db7071c93455880cf0a14027655cbd9sewardj                                    void* send_arg2,
22703ca90b84db7071c93455880cf0a14027655cbd9sewardj                                    HChar* str )
22803ca90b84db7071c93455880cf0a14027655cbd9sewardj{
22903ca90b84db7071c93455880cf0a14027655cbd9sewardj   UInt   ret = 0;
23003ca90b84db7071c93455880cf0a14027655cbd9sewardj   Int    i;
23103ca90b84db7071c93455880cf0a14027655cbd9sewardj   Int    len = local_strlen(str);
23203ca90b84db7071c93455880cf0a14027655cbd9sewardj   HChar* alt;
23303ca90b84db7071c93455880cf0a14027655cbd9sewardj
23403ca90b84db7071c93455880cf0a14027655cbd9sewardj   for (i = 0; i < len; i++) {
23503ca90b84db7071c93455880cf0a14027655cbd9sewardj      switch (str[i]) {
23603ca90b84db7071c93455880cf0a14027655cbd9sewardj         case '&': alt = "&amp;"; break;
23703ca90b84db7071c93455880cf0a14027655cbd9sewardj         case '<': alt = "&lt;"; break;
23803ca90b84db7071c93455880cf0a14027655cbd9sewardj         case '>': alt = "&gt;"; break;
23903ca90b84db7071c93455880cf0a14027655cbd9sewardj         default:  alt = NULL;
24003ca90b84db7071c93455880cf0a14027655cbd9sewardj      }
24103ca90b84db7071c93455880cf0a14027655cbd9sewardj
24203ca90b84db7071c93455880cf0a14027655cbd9sewardj      if (alt) {
24303ca90b84db7071c93455880cf0a14027655cbd9sewardj         while (*alt) {
24403ca90b84db7071c93455880cf0a14027655cbd9sewardj            send(*alt, send_arg2);
24503ca90b84db7071c93455880cf0a14027655cbd9sewardj            ret++;
24603ca90b84db7071c93455880cf0a14027655cbd9sewardj            alt++;
24703ca90b84db7071c93455880cf0a14027655cbd9sewardj         }
24803ca90b84db7071c93455880cf0a14027655cbd9sewardj      } else {
24903ca90b84db7071c93455880cf0a14027655cbd9sewardj         send(str[i], send_arg2);
25003ca90b84db7071c93455880cf0a14027655cbd9sewardj         ret++;
25103ca90b84db7071c93455880cf0a14027655cbd9sewardj      }
25203ca90b84db7071c93455880cf0a14027655cbd9sewardj   }
25303ca90b84db7071c93455880cf0a14027655cbd9sewardj
25403ca90b84db7071c93455880cf0a14027655cbd9sewardj   return ret;
25503ca90b84db7071c93455880cf0a14027655cbd9sewardj}
25603ca90b84db7071c93455880cf0a14027655cbd9sewardj
25703ca90b84db7071c93455880cf0a14027655cbd9sewardj
25803ca90b84db7071c93455880cf0a14027655cbd9sewardj/* Write P into the buffer according to these args:
25903ca90b84db7071c93455880cf0a14027655cbd9sewardj *  If SIGN is true, p is a signed.
26003ca90b84db7071c93455880cf0a14027655cbd9sewardj *  BASE is the base.
26103ca90b84db7071c93455880cf0a14027655cbd9sewardj *  If WITH_ZERO is true, '0' must be added.
26203ca90b84db7071c93455880cf0a14027655cbd9sewardj *  WIDTH is the width of the field.
26303ca90b84db7071c93455880cf0a14027655cbd9sewardj */
26403ca90b84db7071c93455880cf0a14027655cbd9sewardjstatic
26503ca90b84db7071c93455880cf0a14027655cbd9sewardjUInt myvprintf_int64 ( void(*send)(HChar,void*),
26603ca90b84db7071c93455880cf0a14027655cbd9sewardj                       void* send_arg2,
26703ca90b84db7071c93455880cf0a14027655cbd9sewardj                       Int flags,
26803ca90b84db7071c93455880cf0a14027655cbd9sewardj                       Int base,
26903ca90b84db7071c93455880cf0a14027655cbd9sewardj                       Int width,
27003ca90b84db7071c93455880cf0a14027655cbd9sewardj                       Bool capitalised,
27103ca90b84db7071c93455880cf0a14027655cbd9sewardj                       ULong p )
27203ca90b84db7071c93455880cf0a14027655cbd9sewardj{
27303ca90b84db7071c93455880cf0a14027655cbd9sewardj   HChar  buf[40];
27403ca90b84db7071c93455880cf0a14027655cbd9sewardj   Int    ind = 0;
27503ca90b84db7071c93455880cf0a14027655cbd9sewardj   Int    i, nc = 0;
27603ca90b84db7071c93455880cf0a14027655cbd9sewardj   Bool   neg = False;
27703ca90b84db7071c93455880cf0a14027655cbd9sewardj   HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
27803ca90b84db7071c93455880cf0a14027655cbd9sewardj   UInt   ret = 0;
27903ca90b84db7071c93455880cf0a14027655cbd9sewardj
28003ca90b84db7071c93455880cf0a14027655cbd9sewardj   if (base < 2 || base > 16)
28103ca90b84db7071c93455880cf0a14027655cbd9sewardj      return ret;
28203ca90b84db7071c93455880cf0a14027655cbd9sewardj
28303ca90b84db7071c93455880cf0a14027655cbd9sewardj   if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
28403ca90b84db7071c93455880cf0a14027655cbd9sewardj      p   = - (Long)p;
28503ca90b84db7071c93455880cf0a14027655cbd9sewardj      neg = True;
28603ca90b84db7071c93455880cf0a14027655cbd9sewardj   }
28703ca90b84db7071c93455880cf0a14027655cbd9sewardj
28803ca90b84db7071c93455880cf0a14027655cbd9sewardj   if (p == 0)
28903ca90b84db7071c93455880cf0a14027655cbd9sewardj      buf[ind++] = '0';
29003ca90b84db7071c93455880cf0a14027655cbd9sewardj   else {
29103ca90b84db7071c93455880cf0a14027655cbd9sewardj      while (p > 0) {
29203ca90b84db7071c93455880cf0a14027655cbd9sewardj         if (flags & VG_MSG_COMMA && 10 == base &&
29303ca90b84db7071c93455880cf0a14027655cbd9sewardj             0 == (ind-nc) % 3 && 0 != ind)
29403ca90b84db7071c93455880cf0a14027655cbd9sewardj         {
29503ca90b84db7071c93455880cf0a14027655cbd9sewardj            buf[ind++] = ',';
29603ca90b84db7071c93455880cf0a14027655cbd9sewardj            nc++;
29703ca90b84db7071c93455880cf0a14027655cbd9sewardj         }
29803ca90b84db7071c93455880cf0a14027655cbd9sewardj         buf[ind++] = digits[p % base];
29903ca90b84db7071c93455880cf0a14027655cbd9sewardj         p /= base;
30003ca90b84db7071c93455880cf0a14027655cbd9sewardj      }
30103ca90b84db7071c93455880cf0a14027655cbd9sewardj   }
30203ca90b84db7071c93455880cf0a14027655cbd9sewardj
30303ca90b84db7071c93455880cf0a14027655cbd9sewardj   if (neg)
30403ca90b84db7071c93455880cf0a14027655cbd9sewardj      buf[ind++] = '-';
30503ca90b84db7071c93455880cf0a14027655cbd9sewardj
30603ca90b84db7071c93455880cf0a14027655cbd9sewardj   if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
30703ca90b84db7071c93455880cf0a14027655cbd9sewardj      for(; ind < width; ind++) {
30803ca90b84db7071c93455880cf0a14027655cbd9sewardj         /* assert(ind < 39); */
30903ca90b84db7071c93455880cf0a14027655cbd9sewardj         if (ind > 39) {
31003ca90b84db7071c93455880cf0a14027655cbd9sewardj            buf[39] = 0;
31103ca90b84db7071c93455880cf0a14027655cbd9sewardj            break;
31203ca90b84db7071c93455880cf0a14027655cbd9sewardj         }
31303ca90b84db7071c93455880cf0a14027655cbd9sewardj         buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
31403ca90b84db7071c93455880cf0a14027655cbd9sewardj      }
31503ca90b84db7071c93455880cf0a14027655cbd9sewardj   }
31603ca90b84db7071c93455880cf0a14027655cbd9sewardj
31703ca90b84db7071c93455880cf0a14027655cbd9sewardj   /* Reverse copy to buffer.  */
31803ca90b84db7071c93455880cf0a14027655cbd9sewardj   ret += ind;
31903ca90b84db7071c93455880cf0a14027655cbd9sewardj   for (i = ind -1; i >= 0; i--) {
32003ca90b84db7071c93455880cf0a14027655cbd9sewardj      send(buf[i], send_arg2);
32103ca90b84db7071c93455880cf0a14027655cbd9sewardj   }
32203ca90b84db7071c93455880cf0a14027655cbd9sewardj   if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
32303ca90b84db7071c93455880cf0a14027655cbd9sewardj      for(; ind < width; ind++) {
32403ca90b84db7071c93455880cf0a14027655cbd9sewardj         ret++;
32503ca90b84db7071c93455880cf0a14027655cbd9sewardj         /* Never pad with zeroes on RHS -- changes the value! */
32603ca90b84db7071c93455880cf0a14027655cbd9sewardj         send(' ', send_arg2);
32703ca90b84db7071c93455880cf0a14027655cbd9sewardj      }
32803ca90b84db7071c93455880cf0a14027655cbd9sewardj   }
32903ca90b84db7071c93455880cf0a14027655cbd9sewardj   return ret;
33003ca90b84db7071c93455880cf0a14027655cbd9sewardj}
33103ca90b84db7071c93455880cf0a14027655cbd9sewardj
33203ca90b84db7071c93455880cf0a14027655cbd9sewardj
33303ca90b84db7071c93455880cf0a14027655cbd9sewardj/* A simple vprintf().  */
33403ca90b84db7071c93455880cf0a14027655cbd9sewardj/* EXPORTED */
33503ca90b84db7071c93455880cf0a14027655cbd9sewardj__attribute__((noinline))
33603ca90b84db7071c93455880cf0a14027655cbd9sewardjUInt
33703ca90b84db7071c93455880cf0a14027655cbd9sewardjVG_(debugLog_vprintf) (
33803ca90b84db7071c93455880cf0a14027655cbd9sewardj   void(*send)(HChar,void*),
33903ca90b84db7071c93455880cf0a14027655cbd9sewardj   void* send_arg2,
34003ca90b84db7071c93455880cf0a14027655cbd9sewardj   const HChar* format,
34103ca90b84db7071c93455880cf0a14027655cbd9sewardj   va_list vargs
34203ca90b84db7071c93455880cf0a14027655cbd9sewardj)
34303ca90b84db7071c93455880cf0a14027655cbd9sewardj{
34403ca90b84db7071c93455880cf0a14027655cbd9sewardj   UInt ret = 0;
34503ca90b84db7071c93455880cf0a14027655cbd9sewardj   Int  i;
34603ca90b84db7071c93455880cf0a14027655cbd9sewardj   Int  flags;
34703ca90b84db7071c93455880cf0a14027655cbd9sewardj   Int  width;
34803ca90b84db7071c93455880cf0a14027655cbd9sewardj   Int  n_ls = 0;
34903ca90b84db7071c93455880cf0a14027655cbd9sewardj   Bool is_long, caps;
35003ca90b84db7071c93455880cf0a14027655cbd9sewardj
35103ca90b84db7071c93455880cf0a14027655cbd9sewardj   /* We assume that vargs has already been initialised by the
35203ca90b84db7071c93455880cf0a14027655cbd9sewardj      caller, using va_start, and that the caller will similarly
35303ca90b84db7071c93455880cf0a14027655cbd9sewardj      clean up with va_end.
35403ca90b84db7071c93455880cf0a14027655cbd9sewardj   */
35503ca90b84db7071c93455880cf0a14027655cbd9sewardj
35603ca90b84db7071c93455880cf0a14027655cbd9sewardj   for (i = 0; format[i] != 0; i++) {
35703ca90b84db7071c93455880cf0a14027655cbd9sewardj      if (format[i] != '%') {
35803ca90b84db7071c93455880cf0a14027655cbd9sewardj         send(format[i], send_arg2);
35903ca90b84db7071c93455880cf0a14027655cbd9sewardj         ret++;
36003ca90b84db7071c93455880cf0a14027655cbd9sewardj         continue;
36103ca90b84db7071c93455880cf0a14027655cbd9sewardj      }
36203ca90b84db7071c93455880cf0a14027655cbd9sewardj      i++;
36303ca90b84db7071c93455880cf0a14027655cbd9sewardj      /* A '%' has been found.  Ignore a trailing %. */
36403ca90b84db7071c93455880cf0a14027655cbd9sewardj      if (format[i] == 0)
36503ca90b84db7071c93455880cf0a14027655cbd9sewardj         break;
36603ca90b84db7071c93455880cf0a14027655cbd9sewardj      if (format[i] == '%') {
36703ca90b84db7071c93455880cf0a14027655cbd9sewardj         /* '%%' is replaced by '%'. */
36803ca90b84db7071c93455880cf0a14027655cbd9sewardj         send('%', send_arg2);
36903ca90b84db7071c93455880cf0a14027655cbd9sewardj         ret++;
37003ca90b84db7071c93455880cf0a14027655cbd9sewardj         continue;
37103ca90b84db7071c93455880cf0a14027655cbd9sewardj      }
37203ca90b84db7071c93455880cf0a14027655cbd9sewardj      flags = 0;
37303ca90b84db7071c93455880cf0a14027655cbd9sewardj      n_ls  = 0;
37403ca90b84db7071c93455880cf0a14027655cbd9sewardj      width = 0; /* length of the field. */
37503ca90b84db7071c93455880cf0a14027655cbd9sewardj      while (1) {
37603ca90b84db7071c93455880cf0a14027655cbd9sewardj         switch (format[i]) {
37703ca90b84db7071c93455880cf0a14027655cbd9sewardj         case '(':
37803ca90b84db7071c93455880cf0a14027655cbd9sewardj            flags |= VG_MSG_PAREN;
37903ca90b84db7071c93455880cf0a14027655cbd9sewardj            break;
38003ca90b84db7071c93455880cf0a14027655cbd9sewardj         case ',':
38103ca90b84db7071c93455880cf0a14027655cbd9sewardj         case '\'':
38203ca90b84db7071c93455880cf0a14027655cbd9sewardj            /* If ',' or '\'' follows '%', commas will be inserted. */
38303ca90b84db7071c93455880cf0a14027655cbd9sewardj            flags |= VG_MSG_COMMA;
38403ca90b84db7071c93455880cf0a14027655cbd9sewardj            break;
38503ca90b84db7071c93455880cf0a14027655cbd9sewardj         case '-':
38603ca90b84db7071c93455880cf0a14027655cbd9sewardj            /* If '-' follows '%', justify on the left. */
38703ca90b84db7071c93455880cf0a14027655cbd9sewardj            flags |= VG_MSG_LJUSTIFY;
38803ca90b84db7071c93455880cf0a14027655cbd9sewardj            break;
38903ca90b84db7071c93455880cf0a14027655cbd9sewardj         case '0':
39003ca90b84db7071c93455880cf0a14027655cbd9sewardj            /* If '0' follows '%', pads will be inserted. */
39103ca90b84db7071c93455880cf0a14027655cbd9sewardj            flags |= VG_MSG_ZJUSTIFY;
39203ca90b84db7071c93455880cf0a14027655cbd9sewardj            break;
39303ca90b84db7071c93455880cf0a14027655cbd9sewardj         case '#':
39403ca90b84db7071c93455880cf0a14027655cbd9sewardj            /* If '#' follows '%', alternative format will be used. */
39503ca90b84db7071c93455880cf0a14027655cbd9sewardj            flags |= VG_MSG_ALTFORMAT;
39603ca90b84db7071c93455880cf0a14027655cbd9sewardj            break;
39703ca90b84db7071c93455880cf0a14027655cbd9sewardj         default:
39803ca90b84db7071c93455880cf0a14027655cbd9sewardj            goto parse_fieldwidth;
39903ca90b84db7071c93455880cf0a14027655cbd9sewardj         }
40003ca90b84db7071c93455880cf0a14027655cbd9sewardj         i++;
40103ca90b84db7071c93455880cf0a14027655cbd9sewardj      }
40203ca90b84db7071c93455880cf0a14027655cbd9sewardj     parse_fieldwidth:
40303ca90b84db7071c93455880cf0a14027655cbd9sewardj      /* Compute the field length. */
40403ca90b84db7071c93455880cf0a14027655cbd9sewardj      while (format[i] >= '0' && format[i] <= '9') {
40503ca90b84db7071c93455880cf0a14027655cbd9sewardj         width *= 10;
40603ca90b84db7071c93455880cf0a14027655cbd9sewardj         width += format[i++] - '0';
40703ca90b84db7071c93455880cf0a14027655cbd9sewardj      }
40803ca90b84db7071c93455880cf0a14027655cbd9sewardj      while (format[i] == 'l') {
40903ca90b84db7071c93455880cf0a14027655cbd9sewardj         i++;
41003ca90b84db7071c93455880cf0a14027655cbd9sewardj         n_ls++;
41103ca90b84db7071c93455880cf0a14027655cbd9sewardj      }
41203ca90b84db7071c93455880cf0a14027655cbd9sewardj
41303ca90b84db7071c93455880cf0a14027655cbd9sewardj      //   %d means print a 32-bit integer.
41403ca90b84db7071c93455880cf0a14027655cbd9sewardj      //  %ld means print a word-size integer.
41503ca90b84db7071c93455880cf0a14027655cbd9sewardj      // %lld means print a 64-bit integer.
41603ca90b84db7071c93455880cf0a14027655cbd9sewardj      if      (0 == n_ls) { is_long = False; }
41703ca90b84db7071c93455880cf0a14027655cbd9sewardj      else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
41803ca90b84db7071c93455880cf0a14027655cbd9sewardj      else                { is_long = True; }
41903ca90b84db7071c93455880cf0a14027655cbd9sewardj
42003ca90b84db7071c93455880cf0a14027655cbd9sewardj      switch (format[i]) {
42103ca90b84db7071c93455880cf0a14027655cbd9sewardj         case 'o': /* %o */
42203ca90b84db7071c93455880cf0a14027655cbd9sewardj            if (flags & VG_MSG_ALTFORMAT) {
42303ca90b84db7071c93455880cf0a14027655cbd9sewardj               ret += 2;
42403ca90b84db7071c93455880cf0a14027655cbd9sewardj               send('0',send_arg2);
42503ca90b84db7071c93455880cf0a14027655cbd9sewardj            }
42603ca90b84db7071c93455880cf0a14027655cbd9sewardj            if (is_long)
42703ca90b84db7071c93455880cf0a14027655cbd9sewardj               ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
42803ca90b84db7071c93455880cf0a14027655cbd9sewardj                                      (ULong)(va_arg (vargs, ULong)));
42903ca90b84db7071c93455880cf0a14027655cbd9sewardj            else
43003ca90b84db7071c93455880cf0a14027655cbd9sewardj               ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
43103ca90b84db7071c93455880cf0a14027655cbd9sewardj                                      (ULong)(va_arg (vargs, UInt)));
43203ca90b84db7071c93455880cf0a14027655cbd9sewardj            break;
43303ca90b84db7071c93455880cf0a14027655cbd9sewardj         case 'd': /* %d */
43403ca90b84db7071c93455880cf0a14027655cbd9sewardj            flags |= VG_MSG_SIGNED;
43503ca90b84db7071c93455880cf0a14027655cbd9sewardj            if (is_long)
43603ca90b84db7071c93455880cf0a14027655cbd9sewardj               ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
43703ca90b84db7071c93455880cf0a14027655cbd9sewardj                                      (ULong)(va_arg (vargs, Long)));
43803ca90b84db7071c93455880cf0a14027655cbd9sewardj            else
43903ca90b84db7071c93455880cf0a14027655cbd9sewardj               ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
44003ca90b84db7071c93455880cf0a14027655cbd9sewardj                                      (ULong)(va_arg (vargs, Int)));
44103ca90b84db7071c93455880cf0a14027655cbd9sewardj            break;
44203ca90b84db7071c93455880cf0a14027655cbd9sewardj         case 'u': /* %u */
44303ca90b84db7071c93455880cf0a14027655cbd9sewardj            if (is_long)
44403ca90b84db7071c93455880cf0a14027655cbd9sewardj               ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
44503ca90b84db7071c93455880cf0a14027655cbd9sewardj                                      (ULong)(va_arg (vargs, ULong)));
44603ca90b84db7071c93455880cf0a14027655cbd9sewardj            else
44703ca90b84db7071c93455880cf0a14027655cbd9sewardj               ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
44803ca90b84db7071c93455880cf0a14027655cbd9sewardj                                      (ULong)(va_arg (vargs, UInt)));
44903ca90b84db7071c93455880cf0a14027655cbd9sewardj            break;
450b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart         case 'p':
451b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart            if (format[i+1] == 'S') {
452b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               i++;
453b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               /* %pS, like %s but escaping chars for XML safety */
454b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               /* Note: simplistic; ignores field width and flags */
455b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               char *str = va_arg (vargs, char *);
456b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               if (str == (char*) 0)
457b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart                  str = "(null)";
458b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
459b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart            } else {
460b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               /* %p */
461b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               ret += 2;
462b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               send('0',send_arg2);
463b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               send('x',send_arg2);
464b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               ret += myvprintf_int64(send, send_arg2, flags, 16, width, True,
465b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart                                      (ULong)((UWord)va_arg (vargs, void *)));
466b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart            }
46703ca90b84db7071c93455880cf0a14027655cbd9sewardj            break;
46803ca90b84db7071c93455880cf0a14027655cbd9sewardj         case 'x': /* %x */
46903ca90b84db7071c93455880cf0a14027655cbd9sewardj         case 'X': /* %X */
47003ca90b84db7071c93455880cf0a14027655cbd9sewardj            caps = toBool(format[i] == 'X');
47103ca90b84db7071c93455880cf0a14027655cbd9sewardj            if (flags & VG_MSG_ALTFORMAT) {
47203ca90b84db7071c93455880cf0a14027655cbd9sewardj               ret += 2;
47303ca90b84db7071c93455880cf0a14027655cbd9sewardj               send('0',send_arg2);
47403ca90b84db7071c93455880cf0a14027655cbd9sewardj               send('x',send_arg2);
47503ca90b84db7071c93455880cf0a14027655cbd9sewardj            }
47603ca90b84db7071c93455880cf0a14027655cbd9sewardj            if (is_long)
47703ca90b84db7071c93455880cf0a14027655cbd9sewardj               ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
47803ca90b84db7071c93455880cf0a14027655cbd9sewardj                                      (ULong)(va_arg (vargs, ULong)));
47903ca90b84db7071c93455880cf0a14027655cbd9sewardj            else
48003ca90b84db7071c93455880cf0a14027655cbd9sewardj               ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
48103ca90b84db7071c93455880cf0a14027655cbd9sewardj                                      (ULong)(va_arg (vargs, UInt)));
48203ca90b84db7071c93455880cf0a14027655cbd9sewardj            break;
48303ca90b84db7071c93455880cf0a14027655cbd9sewardj         case 'c': /* %c */
48403ca90b84db7071c93455880cf0a14027655cbd9sewardj            ret++;
48503ca90b84db7071c93455880cf0a14027655cbd9sewardj            send(va_arg (vargs, int), send_arg2);
48603ca90b84db7071c93455880cf0a14027655cbd9sewardj            break;
48703ca90b84db7071c93455880cf0a14027655cbd9sewardj         case 's': case 'S': { /* %s */
48803ca90b84db7071c93455880cf0a14027655cbd9sewardj            char *str = va_arg (vargs, char *);
48903ca90b84db7071c93455880cf0a14027655cbd9sewardj            if (str == (char*) 0) str = "(null)";
49003ca90b84db7071c93455880cf0a14027655cbd9sewardj            ret += myvprintf_str(send, send_arg2,
49103ca90b84db7071c93455880cf0a14027655cbd9sewardj                                 flags, width, str, format[i]=='S');
49203ca90b84db7071c93455880cf0a14027655cbd9sewardj            break;
49303ca90b84db7071c93455880cf0a14027655cbd9sewardj         }
49403ca90b84db7071c93455880cf0a14027655cbd9sewardj
49503ca90b84db7071c93455880cf0a14027655cbd9sewardj//         case 'y': { /* %y - print symbol */
49603ca90b84db7071c93455880cf0a14027655cbd9sewardj//            Addr a = va_arg(vargs, Addr);
49703ca90b84db7071c93455880cf0a14027655cbd9sewardj//
49846cc04521acf2827eb33310fadc119bf2dc039e4florian//
49946cc04521acf2827eb33310fadc119bf2dc039e4florian//
50046cc04521acf2827eb33310fadc119bf2dc039e4florian//            HChar *name;
50146cc04521acf2827eb33310fadc119bf2dc039e4florian// 	      if (VG_(get_fnname_w_offset)(a, &name)) {
50246cc04521acf2827eb33310fadc119bf2dc039e4florian//               HChar buf[1 + VG_strlen(name) + 1 + 1];
50346cc04521acf2827eb33310fadc119bf2dc039e4florian// 	         if (flags & VG_MSG_PAREN) {
50446cc04521acf2827eb33310fadc119bf2dc039e4florian//                  VG_(sprintf)(str, "(%s)", name):
50546cc04521acf2827eb33310fadc119bf2dc039e4florian// 	         } else {
50646cc04521acf2827eb33310fadc119bf2dc039e4florian//                  VG_(sprintf)(str, "%s", name):
50703ca90b84db7071c93455880cf0a14027655cbd9sewardj//               }
50846cc04521acf2827eb33310fadc119bf2dc039e4florian// 	         ret += myvprintf_str(send, flags, width, buf, 0);
50946cc04521acf2827eb33310fadc119bf2dc039e4florian// 	      }
51003ca90b84db7071c93455880cf0a14027655cbd9sewardj//            break;
51103ca90b84db7071c93455880cf0a14027655cbd9sewardj//         }
51203ca90b84db7071c93455880cf0a14027655cbd9sewardj         default:
51303ca90b84db7071c93455880cf0a14027655cbd9sewardj            break;
51403ca90b84db7071c93455880cf0a14027655cbd9sewardj      }
51503ca90b84db7071c93455880cf0a14027655cbd9sewardj   }
51603ca90b84db7071c93455880cf0a14027655cbd9sewardj   return ret;
51703ca90b84db7071c93455880cf0a14027655cbd9sewardj}
51803ca90b84db7071c93455880cf0a14027655cbd9sewardj
51903ca90b84db7071c93455880cf0a14027655cbd9sewardj
52003ca90b84db7071c93455880cf0a14027655cbd9sewardjstatic void add_to__sprintf_buf ( HChar c, void *p )
52103ca90b84db7071c93455880cf0a14027655cbd9sewardj{
52203ca90b84db7071c93455880cf0a14027655cbd9sewardj   HChar** b = p;
52303ca90b84db7071c93455880cf0a14027655cbd9sewardj   *(*b)++ = c;
52403ca90b84db7071c93455880cf0a14027655cbd9sewardj}
52503ca90b84db7071c93455880cf0a14027655cbd9sewardj
52603ca90b84db7071c93455880cf0a14027655cbd9sewardjUInt VG_(vsprintf) ( HChar* buf, const HChar *format, va_list vargs )
52703ca90b84db7071c93455880cf0a14027655cbd9sewardj{
52803ca90b84db7071c93455880cf0a14027655cbd9sewardj   Int ret;
52903ca90b84db7071c93455880cf0a14027655cbd9sewardj   HChar* sprintf_ptr = buf;
53003ca90b84db7071c93455880cf0a14027655cbd9sewardj
53103ca90b84db7071c93455880cf0a14027655cbd9sewardj   ret = VG_(debugLog_vprintf)
53203ca90b84db7071c93455880cf0a14027655cbd9sewardj            ( add_to__sprintf_buf, &sprintf_ptr, format, vargs );
53303ca90b84db7071c93455880cf0a14027655cbd9sewardj   add_to__sprintf_buf('\0', &sprintf_ptr);
53403ca90b84db7071c93455880cf0a14027655cbd9sewardj
53503ca90b84db7071c93455880cf0a14027655cbd9sewardj   assert(local_strlen(buf) == ret);
53603ca90b84db7071c93455880cf0a14027655cbd9sewardj
53703ca90b84db7071c93455880cf0a14027655cbd9sewardj   return ret;
53803ca90b84db7071c93455880cf0a14027655cbd9sewardj}
53903ca90b84db7071c93455880cf0a14027655cbd9sewardj
54003ca90b84db7071c93455880cf0a14027655cbd9sewardjUInt VG_(sprintf) ( HChar* buf, const HChar *format, ... )
54103ca90b84db7071c93455880cf0a14027655cbd9sewardj{
54203ca90b84db7071c93455880cf0a14027655cbd9sewardj   UInt ret;
54303ca90b84db7071c93455880cf0a14027655cbd9sewardj   va_list vargs;
54403ca90b84db7071c93455880cf0a14027655cbd9sewardj   va_start(vargs,format);
54503ca90b84db7071c93455880cf0a14027655cbd9sewardj   ret = VG_(vsprintf)(buf, format, vargs);
54603ca90b84db7071c93455880cf0a14027655cbd9sewardj   va_end(vargs);
54703ca90b84db7071c93455880cf0a14027655cbd9sewardj   return ret;
54803ca90b84db7071c93455880cf0a14027655cbd9sewardj}
54903ca90b84db7071c93455880cf0a14027655cbd9sewardj
55003ca90b84db7071c93455880cf0a14027655cbd9sewardj
551024598e40c84666cc311a42c256bbf880db3ac99sewardj
552024598e40c84666cc311a42c256bbf880db3ac99sewardj/* ---------------------------------------------------------------------
553024598e40c84666cc311a42c256bbf880db3ac99sewardj   percentify()
554024598e40c84666cc311a42c256bbf880db3ac99sewardj   ------------------------------------------------------------------ */
555024598e40c84666cc311a42c256bbf880db3ac99sewardj
556024598e40c84666cc311a42c256bbf880db3ac99sewardj/* This part excerpted from coregrind/m_libcbase.c */
557024598e40c84666cc311a42c256bbf880db3ac99sewardj
558024598e40c84666cc311a42c256bbf880db3ac99sewardj// Percentify n/m with d decimal places.  Includes the '%' symbol at the end.
559024598e40c84666cc311a42c256bbf880db3ac99sewardj// Right justifies in 'buf'.
56003ca90b84db7071c93455880cf0a14027655cbd9sewardj__attribute__((noinline))
56103ca90b84db7071c93455880cf0a14027655cbd9sewardjvoid VG_percentify(ULong n, ULong m, UInt d, Int n_buf, HChar buf[])
562024598e40c84666cc311a42c256bbf880db3ac99sewardj{
563024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int i, len, space;
564024598e40c84666cc311a42c256bbf880db3ac99sewardj   ULong p1;
56503ca90b84db7071c93455880cf0a14027655cbd9sewardj   HChar fmt[32];
566024598e40c84666cc311a42c256bbf880db3ac99sewardj
567024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (m == 0) {
568024598e40c84666cc311a42c256bbf880db3ac99sewardj      // Have to generate the format string in order to be flexible about
569024598e40c84666cc311a42c256bbf880db3ac99sewardj      // the width of the field.
57003ca90b84db7071c93455880cf0a14027655cbd9sewardj      VG_(sprintf)(fmt, "%%-%ds", n_buf);
571024598e40c84666cc311a42c256bbf880db3ac99sewardj      // fmt is now "%<n_buf>s" where <d> is 1,2,3...
57203ca90b84db7071c93455880cf0a14027655cbd9sewardj      VG_(sprintf)(buf, fmt, "--%");
573024598e40c84666cc311a42c256bbf880db3ac99sewardj      return;
574024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
575024598e40c84666cc311a42c256bbf880db3ac99sewardj
576024598e40c84666cc311a42c256bbf880db3ac99sewardj   p1 = (100*n) / m;
577024598e40c84666cc311a42c256bbf880db3ac99sewardj
578024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (d == 0) {
57903ca90b84db7071c93455880cf0a14027655cbd9sewardj      VG_(sprintf)(buf, "%lld%%", p1);
580024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
581024598e40c84666cc311a42c256bbf880db3ac99sewardj      ULong p2;
582024598e40c84666cc311a42c256bbf880db3ac99sewardj      UInt  ex;
583024598e40c84666cc311a42c256bbf880db3ac99sewardj      switch (d) {
584024598e40c84666cc311a42c256bbf880db3ac99sewardj      case 1: ex = 10;    break;
585024598e40c84666cc311a42c256bbf880db3ac99sewardj      case 2: ex = 100;   break;
586024598e40c84666cc311a42c256bbf880db3ac99sewardj      case 3: ex = 1000;  break;
587024598e40c84666cc311a42c256bbf880db3ac99sewardj      default: assert(0);
588024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* was: VG_(tool_panic)("Currently can only handle 3 decimal places"); */
589024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
590024598e40c84666cc311a42c256bbf880db3ac99sewardj      p2 = ((100*n*ex) / m) % ex;
591024598e40c84666cc311a42c256bbf880db3ac99sewardj      // Have to generate the format string in order to be flexible about
592024598e40c84666cc311a42c256bbf880db3ac99sewardj      // the width of the post-decimal-point part.
59303ca90b84db7071c93455880cf0a14027655cbd9sewardj      VG_(sprintf)(fmt, "%%lld.%%0%dlld%%%%", d);
594024598e40c84666cc311a42c256bbf880db3ac99sewardj      // fmt is now "%lld.%0<d>lld%%" where <d> is 1,2,3...
59503ca90b84db7071c93455880cf0a14027655cbd9sewardj      VG_(sprintf)(buf, fmt, p1, p2);
596024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
597024598e40c84666cc311a42c256bbf880db3ac99sewardj
59803ca90b84db7071c93455880cf0a14027655cbd9sewardj   len = local_strlen(buf);
599024598e40c84666cc311a42c256bbf880db3ac99sewardj   space = n_buf - len;
600024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (space < 0) space = 0;     /* Allow for v. small field_width */
601024598e40c84666cc311a42c256bbf880db3ac99sewardj   i = len;
602024598e40c84666cc311a42c256bbf880db3ac99sewardj
603024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Right justify in field */
604024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (     ; i >= 0;    i--)  buf[i + space] = buf[i];
605024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (i = 0; i < space; i++)  buf[i] = ' ';
606024598e40c84666cc311a42c256bbf880db3ac99sewardj}
607024598e40c84666cc311a42c256bbf880db3ac99sewardj
608024598e40c84666cc311a42c256bbf880db3ac99sewardj
609024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
610024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Stats                                                ---*/
611024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
612024598e40c84666cc311a42c256bbf880db3ac99sewardj
613024598e40c84666cc311a42c256bbf880db3ac99sewardj/* This part excerpted from coregrind/m_translate.c */
614024598e40c84666cc311a42c256bbf880db3ac99sewardj
615024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic UInt n_SP_updates_fast            = 0;
616024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic UInt n_SP_updates_generic_known   = 0;
617024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic UInt n_SP_updates_generic_unknown = 0;
618024598e40c84666cc311a42c256bbf880db3ac99sewardj
61903ca90b84db7071c93455880cf0a14027655cbd9sewardj__attribute__((noinline))
620024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid VG_print_translation_stats ( void )
621024598e40c84666cc311a42c256bbf880db3ac99sewardj{
62203ca90b84db7071c93455880cf0a14027655cbd9sewardj   HChar buf[6];
623024598e40c84666cc311a42c256bbf880db3ac99sewardj   UInt n_SP_updates = n_SP_updates_fast + n_SP_updates_generic_known
624024598e40c84666cc311a42c256bbf880db3ac99sewardj                                         + n_SP_updates_generic_unknown;
625024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_percentify(n_SP_updates_fast, n_SP_updates, 1, 6, buf);
62603ca90b84db7071c93455880cf0a14027655cbd9sewardj   VG_(printf)(
627024598e40c84666cc311a42c256bbf880db3ac99sewardj      "translate:            fast SP updates identified: %'u (%s)\n",
628024598e40c84666cc311a42c256bbf880db3ac99sewardj      n_SP_updates_fast, buf );
629024598e40c84666cc311a42c256bbf880db3ac99sewardj
630024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_percentify(n_SP_updates_generic_known, n_SP_updates, 1, 6, buf);
63103ca90b84db7071c93455880cf0a14027655cbd9sewardj   VG_(printf)(
632024598e40c84666cc311a42c256bbf880db3ac99sewardj      "translate:   generic_known SP updates identified: %'u (%s)\n",
633024598e40c84666cc311a42c256bbf880db3ac99sewardj      n_SP_updates_generic_known, buf );
634024598e40c84666cc311a42c256bbf880db3ac99sewardj
635024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_percentify(n_SP_updates_generic_unknown, n_SP_updates, 1, 6, buf);
63603ca90b84db7071c93455880cf0a14027655cbd9sewardj   VG_(printf)(
637024598e40c84666cc311a42c256bbf880db3ac99sewardj      "translate: generic_unknown SP updates identified: %'u (%s)\n",
638024598e40c84666cc311a42c256bbf880db3ac99sewardj      n_SP_updates_generic_unknown, buf );
639024598e40c84666cc311a42c256bbf880db3ac99sewardj}
640024598e40c84666cc311a42c256bbf880db3ac99sewardj
641024598e40c84666cc311a42c256bbf880db3ac99sewardj
642024598e40c84666cc311a42c256bbf880db3ac99sewardj
643024598e40c84666cc311a42c256bbf880db3ac99sewardjint main ( void )
644024598e40c84666cc311a42c256bbf880db3ac99sewardj{
645024598e40c84666cc311a42c256bbf880db3ac99sewardj  VG_print_translation_stats();
646024598e40c84666cc311a42c256bbf880db3ac99sewardj  return 0;
647024598e40c84666cc311a42c256bbf880db3ac99sewardj}
648