1b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* This demonstrates a stack overrun bug that exp-ptrcheck found while
3b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   running Valgrind itself (self hosting).  As at 12 Sept 08 this bug
4b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   is still in Valgrind. */
5b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
6b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <stdio.h>
7b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <assert.h>
8b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <stdarg.h>
9b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef  unsigned long long int  ULong;
11b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef    signed long long int  Long;
12b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef  unsigned int            UInt;
13b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef  signed int              Int;
14b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef  signed char             Char;
15b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef  char                    HChar;
16b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef unsigned long            UWord;
17b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef   signed long            Word;
18b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
19b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
20b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
21b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef  unsigned char  Bool;
22b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define  True   ((Bool)1)
23b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define  False  ((Bool)0)
24b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
25b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define VG_(_str) VG_##_str
26b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
27b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
28b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* ---------------------------------------------------------------------
29b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vg_sprintf, copied from m_libcprint.c
30b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ------------------------------------------------------------------ */
31b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovUInt
32b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovVG_(debugLog_vprintf) (
33b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void(*send)(HChar,void*),
34b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* send_arg2,
35b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   const HChar* format,
36b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   va_list vargs
37b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        );
38b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
39b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* ---------------------------------------------------------------------
40b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   printf() and friends
41b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ------------------------------------------------------------------ */
42b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef
43b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   struct { Int fd; Bool is_socket; }
44b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   OutputSink;
45b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
46b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
47b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovOutputSink VG_(log_output_sink) = {  2, False }; /* 2 = stderr */
48b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
49b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Do the low-level send of a message to the logging sink. */
50b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic
51b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid send_bytes_to_logging_sink ( OutputSink* sink, HChar* msg, Int nbytes )
52b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
53b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   fwrite(msg, 1, nbytes, stdout);
54b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   fflush(stdout);
55b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
56b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
57b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
58b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* --------- printf --------- */
59b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
60b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef
61b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   struct {
62b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      HChar       buf[512];
63b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Int         buf_used;
64b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      OutputSink* sink;
65b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
66b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   printf_buf_t;
67b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
68b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// Adds a single char to the buffer.  When the buffer gets sufficiently
69b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// full, we write its contents to the logging sink.
70b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void add_to__printf_buf ( HChar c, void *p )
71b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
72b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   printf_buf_t *b = (printf_buf_t *)p;
73b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
74b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (b->buf_used > sizeof(b->buf) - 2 ) {
75b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
76b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      b->buf_used = 0;
77b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
78b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   b->buf[b->buf_used++] = c;
79b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   b->buf[b->buf_used]   = 0;
80b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assert(b->buf_used < sizeof(b->buf));
81b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
82b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
83b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
84b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UInt vprintf_to_buf ( printf_buf_t* b,
85b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             const HChar *format, va_list vargs )
86b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
87b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt ret = 0;
88b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (b->sink->fd >= 0 || b->sink->fd == -2) {
89b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ret = VG_(debugLog_vprintf)
90b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               ( add_to__printf_buf, b, format, vargs );
91b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
92b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return ret;
93b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
94b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
95b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
96b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UInt vprintf_WRK ( OutputSink* sink,
97b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          const HChar *format, va_list vargs )
98b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
99b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   printf_buf_t myprintf_buf
100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      = { "", 0, sink };
101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt ret;
102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ret = vprintf_to_buf(&myprintf_buf, format, vargs);
103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // Write out any chars left in the buffer.
104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (myprintf_buf.buf_used > 0) {
105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      send_bytes_to_logging_sink( myprintf_buf.sink,
106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  myprintf_buf.buf,
107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  myprintf_buf.buf_used );
108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return ret;
110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovUInt VG_(vprintf) ( const HChar *format, va_list vargs )
114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return vprintf_WRK( &VG_(log_output_sink), format, vargs );
116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovUInt VG_(printf) ( const HChar *format, ... )
120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt ret;
122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   va_list vargs;
123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   va_start(vargs, format);
124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ret = VG_(vprintf)(format, vargs);
125b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   va_end(vargs);
126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return ret;
127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool toBool ( Int x ) {
130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int r = (x == 0) ? False : True;
131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return (Bool)r;
132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
133b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
134b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
135b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Int local_strlen ( const HChar* str )
136b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int i = 0;
138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   while (str[i] != 0) i++;
139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return i;
140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
142b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic HChar local_toupper ( HChar c )
144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (c >= 'a' && c <= 'z')
146b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return c + ('A' - 'a');
147b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   else
148b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return c;
149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
151b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
152b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*------------------------------------------------------------*/
153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--- A simple, generic, vprintf implementation.           ---*/
154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*------------------------------------------------------------*/
155b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
156b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* -----------------------------------------------
157b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Distantly derived from:
158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vprintf replacement for Checker.
160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Copyright 1993, 1994, 1995 Tristan Gingold
161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Written September 1993 Tristan Gingold
162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
163b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
164b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   (Checker itself was GPL'd.)
165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ----------------------------------------------- */
166b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Some flags.  */
168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define VG_MSG_SIGNED    1 /* The value is signed. */
169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define VG_MSG_ZJUSTIFY  2 /* Must justify with '0'. */
170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define VG_MSG_LJUSTIFY  4 /* Must justify on the left. */
171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define VG_MSG_PAREN     8 /* Parenthesize if present (for %y) */
172b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define VG_MSG_COMMA    16 /* Add commas to numbers (for %d, %u) */
173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
175b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Copy a string into the buffer. */
176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic __attribute__((noinline))
177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovUInt myvprintf_str ( void(*send)(HChar,void*),
178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     void* send_arg2,
179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     Int flags,
180b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     Int width,
181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     HChar* str,
182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     Bool capitalise )
183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#  define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt ret = 0;
186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int i, extra;
187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int len = local_strlen(str);
188b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (width == 0) {
190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ret += len;
191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      for (i = 0; i < len; i++)
192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          send(MAYBE_TOUPPER(str[i]), send_arg2);
193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return ret;
194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
195b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (len > width) {
197b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ret += width;
198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      for (i = 0; i < width; i++)
199b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         send(MAYBE_TOUPPER(str[i]), send_arg2);
200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return ret;
201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
202b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
203b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   extra = width - len;
204b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (flags & VG_MSG_LJUSTIFY) {
205b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ret += extra;
206b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      for (i = 0; i < extra; i++)
207b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         send(' ', send_arg2);
208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
209b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ret += len;
210b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < len; i++)
211b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      send(MAYBE_TOUPPER(str[i]), send_arg2);
212b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (!(flags & VG_MSG_LJUSTIFY)) {
213b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ret += extra;
214b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      for (i = 0; i < extra; i++)
215b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         send(' ', send_arg2);
216b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
217b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
218b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#  undef MAYBE_TOUPPER
219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return ret;
220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Copy a string into the buffer, escaping bad XML chars. */
224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic
225b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovUInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    void* send_arg2,
227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    HChar* str )
228b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
229b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt   ret = 0;
230b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int    i;
231b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int    len = local_strlen(str);
232b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   HChar* alt;
233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
234b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < len; i++) {
235b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      switch (str[i]) {
236b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case '&': alt = "&amp;"; break;
237b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case '<': alt = "&lt;"; break;
238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case '>': alt = "&gt;"; break;
239b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         default:  alt = NULL;
240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
242b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (alt) {
243b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         while (*alt) {
244b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            send(*alt, send_arg2);
245b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ret++;
246b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            alt++;
247b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
248b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      } else {
249b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         send(str[i], send_arg2);
250b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         ret++;
251b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
252b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
253b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
254b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return ret;
255b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Write P into the buffer according to these args:
259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  If SIGN is true, p is a signed.
260b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  BASE is the base.
261b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  If WITH_ZERO is true, '0' must be added.
262b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  WIDTH is the width of the field.
263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic
265b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovUInt myvprintf_int64 ( void(*send)(HChar,void*),
266b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       void* send_arg2,
267b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       Int flags,
268b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       Int base,
269b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       Int width,
270b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       Bool capitalised,
271b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       ULong p )
272b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
273b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   HChar  buf[40];
274b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int    ind = 0;
275b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int    i, nc = 0;
276b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Bool   neg = False;
277b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
278b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt   ret = 0;
279b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
280b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (base < 2 || base > 16)
281b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return ret;
282b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
283b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
284b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      p   = - (Long)p;
285b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      neg = True;
286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
288b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (p == 0)
289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      buf[ind++] = '0';
290b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   else {
291b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      while (p > 0) {
292b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (flags & VG_MSG_COMMA && 10 == base &&
293b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             0 == (ind-nc) % 3 && 0 != ind)
294b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         {
295b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            buf[ind++] = ',';
296b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            nc++;
297b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
298b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         buf[ind++] = digits[p % base];
299b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         p /= base;
300b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
303b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (neg)
304b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      buf[ind++] = '-';
305b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
306b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
307b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      for(; ind < width; ind++) {
308b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* assert(ind < 39); */
309b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (ind > 39) {
310b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            buf[39] = 0;
311b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
312b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
313b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
315b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
316b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Reverse copy to buffer.  */
318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ret += ind;
319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = ind -1; i >= 0; i--) {
320b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      send(buf[i], send_arg2);
321b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
322b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
323b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      for(; ind < width; ind++) {
324b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         ret++;
325b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Never pad with zeroes on RHS -- changes the value! */
326b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         send(' ', send_arg2);
327b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return ret;
330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
331b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
332b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
333b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* A simple vprintf().  */
334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* EXPORTED */
335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovUInt
337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovVG_(debugLog_vprintf) (
338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void(*send)(HChar,void*),
339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void* send_arg2,
340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   const HChar* format,
341b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   va_list vargs
342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov)
343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt ret = 0;
345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int  i;
346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int  flags;
347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int  width;
348b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int  n_ls = 0;
349b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Bool is_long, caps;
350b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
351b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* We assume that vargs has already been initialised by the
352b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      caller, using va_start, and that the caller will similarly
353b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      clean up with va_end.
354b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   */
355b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
356b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; format[i] != 0; i++) {
357b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (format[i] != '%') {
358b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         send(format[i], send_arg2);
359b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         ret++;
360b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         continue;
361b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      i++;
363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* A '%' has been found.  Ignore a trailing %. */
364b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (format[i] == 0)
365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (format[i] == '%') {
367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* '%%' is replaced by '%'. */
368b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         send('%', send_arg2);
369b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         ret++;
370b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         continue;
371b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
372b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      flags = 0;
373b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      n_ls  = 0;
374b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      width = 0; /* length of the field. */
375b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      while (1) {
376b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         switch (format[i]) {
377b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case '(':
378b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            flags |= VG_MSG_PAREN;
379b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
380b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case ',':
381b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case '\'':
382b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* If ',' or '\'' follows '%', commas will be inserted. */
383b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            flags |= VG_MSG_COMMA;
384b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
385b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case '-':
386b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* If '-' follows '%', justify on the left. */
387b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            flags |= VG_MSG_LJUSTIFY;
388b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
389b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case '0':
390b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* If '0' follows '%', pads will be inserted. */
391b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            flags |= VG_MSG_ZJUSTIFY;
392b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case '#':
394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* If '#' follows '%', alternative format will be used. */
395b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            flags |= VG_MSG_ALTFORMAT;
396b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
397b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         default:
398b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            goto parse_fieldwidth;
399b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
400b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         i++;
401b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
402b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     parse_fieldwidth:
403b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Compute the field length. */
404b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      while (format[i] >= '0' && format[i] <= '9') {
405b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         width *= 10;
406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         width += format[i++] - '0';
407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
408b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      while (format[i] == 'l') {
409b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         i++;
410b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         n_ls++;
411b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
412b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
413b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      //   %d means print a 32-bit integer.
414b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      //  %ld means print a word-size integer.
415b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // %lld means print a 64-bit integer.
416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if      (0 == n_ls) { is_long = False; }
417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
418b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else                { is_long = True; }
419b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      switch (format[i]) {
421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 'o': /* %o */
422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (flags & VG_MSG_ALTFORMAT) {
423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               ret += 2;
424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               send('0',send_arg2);
425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            }
426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (is_long)
427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      (ULong)(va_arg (vargs, ULong)));
429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            else
430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      (ULong)(va_arg (vargs, UInt)));
432b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
433b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 'd': /* %d */
434b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            flags |= VG_MSG_SIGNED;
435b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (is_long)
436b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
437b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      (ULong)(va_arg (vargs, Long)));
438b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            else
439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      (ULong)(va_arg (vargs, Int)));
441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 'u': /* %u */
443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (is_long)
444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      (ULong)(va_arg (vargs, ULong)));
446b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            else
447b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      (ULong)(va_arg (vargs, UInt)));
449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 'p':
451b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (format[i+1] == 'S') {
452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               i++;
453b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               /* %pS, like %s but escaping chars for XML safety */
454b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               /* Note: simplistic; ignores field width and flags */
455b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               char *str = va_arg (vargs, char *);
456b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               if (str == (char*) 0)
457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  str = "(null)";
458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            } else {
460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               /* %p */
461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               ret += 2;
462b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               send('0',send_arg2);
463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               send('x',send_arg2);
464b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               ret += myvprintf_int64(send, send_arg2, flags, 16, width, True,
465b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      (ULong)((UWord)va_arg (vargs, void *)));
466b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            }
467b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
468b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 'x': /* %x */
469b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 'X': /* %X */
470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            caps = toBool(format[i] == 'X');
471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (flags & VG_MSG_ALTFORMAT) {
472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               ret += 2;
473b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               send('0',send_arg2);
474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               send('x',send_arg2);
475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            }
476b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (is_long)
477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      (ULong)(va_arg (vargs, ULong)));
479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            else
480b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
481b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      (ULong)(va_arg (vargs, UInt)));
482b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 'c': /* %c */
484b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ret++;
485b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            send(va_arg (vargs, int), send_arg2);
486b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
487b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 's': case 'S': { /* %s */
488b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            char *str = va_arg (vargs, char *);
489b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (str == (char*) 0) str = "(null)";
490b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ret += myvprintf_str(send, send_arg2,
491b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 flags, width, str, format[i]=='S');
492b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
493b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
494b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
495b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//         case 'y': { /* %y - print symbol */
496b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//            Char buf[100];
497b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//            Char *cp = buf;
498b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//            Addr a = va_arg(vargs, Addr);
499b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//
500b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//            if (flags & VG_MSG_PAREN)
501b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//               *cp++ = '(';
502b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//            if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
503b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//               if (flags & VG_MSG_PAREN) {
504b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//                  cp += local_strlen(cp);
505b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//                  *cp++ = ')';
506b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//                  *cp = '\0';
507b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//               }
508b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//               ret += myvprintf_str(send, send_arg2, flags, width, buf, 0);
509b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//            }
510b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//            break;
511b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//         }
512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         default:
513b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            break;
514b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
515b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return ret;
517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
518b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
519b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
520b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void add_to__sprintf_buf ( HChar c, void *p )
521b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
522b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   HChar** b = p;
523b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   *(*b)++ = c;
524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovUInt VG_(vsprintf) ( HChar* buf, const HChar *format, va_list vargs )
527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int ret;
529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   HChar* sprintf_ptr = buf;
530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ret = VG_(debugLog_vprintf)
532b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ( add_to__sprintf_buf, &sprintf_ptr, format, vargs );
533b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   add_to__sprintf_buf('\0', &sprintf_ptr);
534b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
535b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assert(local_strlen(buf) == ret);
536b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
537b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return ret;
538b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
539b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
540b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovUInt VG_(sprintf) ( HChar* buf, const HChar *format, ... )
541b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
542b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt ret;
543b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   va_list vargs;
544b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   va_start(vargs,format);
545b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ret = VG_(vsprintf)(buf, format, vargs);
546b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   va_end(vargs);
547b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return ret;
548b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
549b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
550b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
551b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* ---------------------------------------------------------------------
553b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   percentify()
554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ------------------------------------------------------------------ */
555b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
556b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* This part excerpted from coregrind/m_libcbase.c */
557b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
558b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// Percentify n/m with d decimal places.  Includes the '%' symbol at the end.
559b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// Right justifies in 'buf'.
560b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
561b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid VG_percentify(ULong n, ULong m, UInt d, Int n_buf, HChar buf[])
562b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
563b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int i, len, space;
564b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ULong p1;
565b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   HChar fmt[32];
566b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
567b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (m == 0) {
568b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // Have to generate the format string in order to be flexible about
569b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // the width of the field.
570b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(sprintf)(fmt, "%%-%ds", n_buf);
571b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // fmt is now "%<n_buf>s" where <d> is 1,2,3...
572b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(sprintf)(buf, fmt, "--%");
573b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return;
574b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
575b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
576b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   p1 = (100*n) / m;
577b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
578b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (d == 0) {
579b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(sprintf)(buf, "%lld%%", p1);
580b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else {
581b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ULong p2;
582b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt  ex;
583b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      switch (d) {
584b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 1: ex = 10;    break;
585b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 2: ex = 100;   break;
586b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 3: ex = 1000;  break;
587b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default: assert(0);
588b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* was: VG_(tool_panic)("Currently can only handle 3 decimal places"); */
589b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
590b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      p2 = ((100*n*ex) / m) % ex;
591b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // Have to generate the format string in order to be flexible about
592b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // the width of the post-decimal-point part.
593b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(sprintf)(fmt, "%%lld.%%0%dlld%%%%", d);
594b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // fmt is now "%lld.%0<d>lld%%" where <d> is 1,2,3...
595b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(sprintf)(buf, fmt, p1, p2);
596b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
597b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
598b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   len = local_strlen(buf);
599b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   space = n_buf - len;
600b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (space < 0) space = 0;     /* Allow for v. small field_width */
601b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   i = len;
602b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
603b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Right justify in field */
604b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (     ; i >= 0;    i--)  buf[i + space] = buf[i];
605b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < space; i++)  buf[i] = ' ';
606b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
607b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
608b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
609b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*------------------------------------------------------------*/
610b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--- Stats                                                ---*/
611b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*------------------------------------------------------------*/
612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* This part excerpted from coregrind/m_translate.c */
614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UInt n_SP_updates_fast            = 0;
616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UInt n_SP_updates_generic_known   = 0;
617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UInt n_SP_updates_generic_unknown = 0;
618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid VG_print_translation_stats ( void )
621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   HChar buf[6];
623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt n_SP_updates = n_SP_updates_fast + n_SP_updates_generic_known
624b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                         + n_SP_updates_generic_unknown;
625b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_percentify(n_SP_updates_fast, n_SP_updates, 1, 6, buf);
626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(printf)(
627b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      "translate:            fast SP updates identified: %'u (%s)\n",
628b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      n_SP_updates_fast, buf );
629b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
630b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_percentify(n_SP_updates_generic_known, n_SP_updates, 1, 6, buf);
631b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(printf)(
632b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      "translate:   generic_known SP updates identified: %'u (%s)\n",
633b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      n_SP_updates_generic_known, buf );
634b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
635b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_percentify(n_SP_updates_generic_unknown, n_SP_updates, 1, 6, buf);
636b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(printf)(
637b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      "translate: generic_unknown SP updates identified: %'u (%s)\n",
638b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      n_SP_updates_generic_unknown, buf );
639b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
640b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
641b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
642b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
643b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovint main ( void )
644b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
645b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  VG_print_translation_stats();
646b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  return 0;
647b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
648