1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- begin                                       main_util.c ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Valgrind, a dynamic binary instrumentation
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   framework.
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Copyright (C) 2004-2013 OpenWorks LLP
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      info@open-works.net
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02110-1301, USA.
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Neither the names of the U.S. Department of Energy nor the
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   University of California nor the names of its contributors may be
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   used to endorse or promote products derived from this software
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   without prior written permission.
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_basictypes.h"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex.h"
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_globals.h"
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_util.h"
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Storage                                           ---*/
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Try to keep this as low as possible -- in particular, less than the
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   size of the smallest L2 cache we might encounter.  At 50000, my VIA
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Nehemiah 1 GHz (a weedy machine) can satisfy 27 million calls/
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   second to LibVEX_Alloc(16) -- that is, allocate memory at over 400
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MByte/sec.  Once the size increases enough to fall out of the cache
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   into memory, the rate falls by about a factor of 3.
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define N_TEMPORARY_BYTES 5000000
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar  temporary[N_TEMPORARY_BYTES] __attribute__((aligned(8)));
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* temporary_first = &temporary[0];
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* temporary_curr  = &temporary[0];
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* temporary_last  = &temporary[N_TEMPORARY_BYTES-1];
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong  temporary_bytes_allocd_TOT = 0;
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define N_PERMANENT_BYTES 10000
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar  permanent[N_PERMANENT_BYTES] __attribute__((aligned(8)));
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* permanent_first = &permanent[0];
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* permanent_curr  = &permanent[0];
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* permanent_last  = &permanent[N_PERMANENT_BYTES-1];
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VexAllocMode mode = VexAllocModeTEMP;
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vexAllocSanityCheck ( void )
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(temporary_first == &temporary[0]);
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(temporary_last  == &temporary[N_TEMPORARY_BYTES-1]);
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(permanent_first == &permanent[0]);
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(permanent_last  == &permanent[N_PERMANENT_BYTES-1]);
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(temporary_first <= temporary_curr);
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(temporary_curr  <= temporary_last);
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(permanent_first <= permanent_curr);
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(permanent_curr  <= permanent_last);
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(private_LibVEX_alloc_first <= private_LibVEX_alloc_curr);
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(private_LibVEX_alloc_curr  <= private_LibVEX_alloc_last);
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mode == VexAllocModeTEMP){
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(private_LibVEX_alloc_first == temporary_first);
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(private_LibVEX_alloc_last  == temporary_last);
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mode == VexAllocModePERM) {
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(private_LibVEX_alloc_first == permanent_first);
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(private_LibVEX_alloc_last  == permanent_last);
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(0);
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define IS_WORD_ALIGNED(p)   (0 == (((HWord)p) & (sizeof(HWord)-1)))
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sizeof(HWord) == 4 || sizeof(HWord) == 8);
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(IS_WORD_ALIGNED(temporary_first));
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(IS_WORD_ALIGNED(temporary_curr));
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(IS_WORD_ALIGNED(temporary_last+1));
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(IS_WORD_ALIGNED(permanent_first));
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(IS_WORD_ALIGNED(permanent_curr));
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(IS_WORD_ALIGNED(permanent_last+1));
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_first));
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_curr));
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_last+1));
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef IS_WORD_ALIGNED
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The current allocation mode. */
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vexSetAllocMode ( VexAllocMode m )
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vexAllocSanityCheck();
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Save away the current allocation point .. */
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mode == VexAllocModeTEMP){
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      temporary_curr = private_LibVEX_alloc_curr;
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mode == VexAllocModePERM) {
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      permanent_curr = private_LibVEX_alloc_curr;
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(0);
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Did that screw anything up? */
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vexAllocSanityCheck();
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (m == VexAllocModeTEMP){
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      private_LibVEX_alloc_first = temporary_first;
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      private_LibVEX_alloc_curr  = temporary_curr;
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      private_LibVEX_alloc_last  = temporary_last;
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (m == VexAllocModePERM) {
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      private_LibVEX_alloc_first = permanent_first;
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      private_LibVEX_alloc_curr  = permanent_curr;
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      private_LibVEX_alloc_last  = permanent_last;
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(0);
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mode = m;
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVexAllocMode vexGetAllocMode ( void )
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return mode;
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Visible to library client, unfortunately. */
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* private_LibVEX_alloc_first = &temporary[0];
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* private_LibVEX_alloc_curr  = &temporary[0];
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* private_LibVEX_alloc_last  = &temporary[N_TEMPORARY_BYTES-1];
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((noreturn))
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid private_LibVEX_alloc_OOM(void)
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
161436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const HChar* pool = "???";
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (private_LibVEX_alloc_first == &temporary[0]) pool = "TEMP";
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (private_LibVEX_alloc_first == &permanent[0]) pool = "PERM";
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("VEX temporary storage exhausted.\n");
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("Pool = %s,  start %p curr %p end %p (size %lld)\n",
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pool,
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              private_LibVEX_alloc_first,
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              private_LibVEX_alloc_curr,
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              private_LibVEX_alloc_last,
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              (Long)(private_LibVEX_alloc_last + 1 - private_LibVEX_alloc_first));
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("VEX temporary storage exhausted.\n"
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          "Increase N_{TEMPORARY,PERMANENT}_BYTES and recompile.");
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vexSetAllocModeTEMP_and_clear ( void )
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* vassert(vex_initdone); */ /* causes infinite assert loops */
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   temporary_bytes_allocd_TOT
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      += (ULong)(private_LibVEX_alloc_curr - private_LibVEX_alloc_first);
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mode = VexAllocModeTEMP;
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   temporary_curr            = &temporary[0];
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   private_LibVEX_alloc_curr = &temporary[0];
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set to (1) and change the fill byte to 0x00 or 0xFF to test for
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      any potential bugs due to using uninitialised memory in the main
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VEX storage area. */
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) {
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int i;
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < N_TEMPORARY_BYTES; i++)
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         temporary[i] = 0x00;
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vexAllocSanityCheck();
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Exported to library client. */
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid LibVEX_ShowAllocStats ( void )
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("vex storage: T total %lld bytes allocated\n",
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              (Long)temporary_bytes_allocd_TOT );
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("vex storage: P total %lld bytes allocated\n",
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              (Long)(permanent_curr - permanent_first) );
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Bombing out                                       ---*/
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__ ((noreturn))
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vex_assert_fail ( const HChar* expr,
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       const HChar* file, Int line, const HChar* fn )
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf( "\nvex: %s:%d (%s): Assertion `%s' failed.\n",
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               file, line, fn, expr );
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*vex_failure_exit)();
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__ ((noreturn))
223436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid vpanic ( const HChar* str )
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\nvex: the `impossible' happened:\n   %s\n", str);
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*vex_failure_exit)();
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- vex_printf                                        ---*/
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This should be the only <...> include in the entire VEX library.
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   New code for vex_util.c should go above this point. */
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdarg.h>
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovInt vex_strlen ( const HChar* str )
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i = 0;
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (str[i] != 0) i++;
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool vex_streq ( const HChar* s1, const HChar* s2 )
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (True) {
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (*s1 == 0 && *s2 == 0)
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (*s1 != *s2)
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      s1++;
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      s2++;
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid vex_bzero ( void* sV, UInt n )
258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt i;
260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar* s = (UChar*)sV;
261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* No laughing, please.  Just don't call this too often.  Thank you
262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for your attention. */
263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i < n; i++) s[i] = 0;
264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Convert N0 into ascii in BUF, which is assumed to be big enough (at
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   least 67 bytes long).  Observe BASE, SYNED and HEXCAPS. */
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid convert_int ( /*OUT*/HChar* buf, Long n0,
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Int base, Bool syned, Bool hexcaps )
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong u0;
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar c;
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool minus = False;
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i, j, bufi = 0;
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   buf[bufi] = 0;
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (syned) {
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (n0 < 0) {
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         minus = True;
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         u0 = (ULong)(-n0);
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         u0 = (ULong)(n0);
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      u0 = (ULong)n0;
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (1) {
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     buf[bufi++] = toHChar('0' + toUInt(u0 % base));
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     u0 /= base;
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (u0 == 0) break;
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (minus)
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      buf[bufi++] = '-';
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   buf[bufi] = 0;
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bufi; i++)
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (buf[i] > '9')
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         buf[i] = toHChar(buf[i] + (hexcaps ? 'A' : 'a') - '9' - 1);
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i = 0;
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   j = bufi-1;
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (i <= j) {
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      c = buf[i];
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      buf[i] = buf[j];
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      buf[j] = c;
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      i++;
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      j--;
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A half-arsed and buggy, but good-enough, implementation of
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   printf. */
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt vprintf_wrk ( void(*sink)(HChar),
319436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   const HChar* format,
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   va_list ap )
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define PUT(_ch)  \
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do { sink(_ch); nout++; } \
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (0)
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define PAD(_n) \
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do { Int _qq = (_n); for (; _qq > 0; _qq--) PUT(padchar); } \
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (0)
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define PUTSTR(_str) \
331436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      do { const HChar* _qq = _str; for (; *_qq; _qq++) PUT(*_qq); } \
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (0)
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
334436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const HChar* saved_format;
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool   longlong, ljustify;
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar  padchar;
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    fwidth, nout, len1, len2, len3;
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar  intbuf[100];  /* big enough for a 64-bit # in base 2 */
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   nout = 0;
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (1) {
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!format)
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (*format == 0)
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (*format != '%') {
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PUT(*format);
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         format++;
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      saved_format = format;
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      longlong = False;
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ljustify = False;
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      padchar = ' ';
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fwidth = 0;
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      format++;
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (*format == '-') {
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         format++;
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ljustify = True;
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (*format == '0') {
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         format++;
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         padchar = '0';
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
369436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (*format == '*') {
370436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         fwidth = va_arg(ap, Int);
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         format++;
372436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      } else {
373436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         while (*format >= '0' && *format <= '9') {
374436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            fwidth = fwidth * 10 + (*format - '0');
375436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            format++;
376436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (*format == 'l') {
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         format++;
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (*format == 'l') {
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            format++;
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           longlong = True;
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (*format) {
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 's': {
388436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            const HChar* str = va_arg(ap, HChar*);
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (str == NULL)
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               str = "(null)";
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len1 = len3 = 0;
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len2 = vex_strlen(str);
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 len3 = ljustify ? fwidth-len2 : 0; }
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PAD(len1); PUTSTR(str); PAD(len3);
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 'c': {
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HChar c = (HChar)va_arg(ap, int);
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HChar str[2];
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            str[0] = c;
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            str[1] = 0;
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len1 = len3 = 0;
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len2 = vex_strlen(str);
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 len3 = ljustify ? fwidth-len2 : 0; }
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PAD(len1); PUTSTR(str); PAD(len3);
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 'd': {
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Long l;
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (longlong) {
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               l = va_arg(ap, Long);
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               l = (Long)va_arg(ap, Int);
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            convert_int(intbuf, l, 10/*base*/, True/*signed*/,
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                False/*irrelevant*/);
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len1 = len3 = 0;
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len2 = vex_strlen(intbuf);
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 len3 = ljustify ? fwidth-len2 : 0; }
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PAD(len1); PUTSTR(intbuf); PAD(len3);
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 'u':
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 'x':
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 'X': {
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Int   base = *format == 'u' ? 10 : 16;
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Bool  hexcaps = True; /* *format == 'X'; */
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong l;
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (longlong) {
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               l = va_arg(ap, ULong);
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               l = (ULong)va_arg(ap, UInt);
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            convert_int(intbuf, l, base, False/*unsigned*/, hexcaps);
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len1 = len3 = 0;
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len2 = vex_strlen(intbuf);
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 len3 = ljustify ? fwidth-len2 : 0; }
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PAD(len1); PUTSTR(intbuf); PAD(len3);
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 'p':
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 'P': {
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Bool hexcaps = toBool(*format == 'P');
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong l = Ptr_to_ULong( va_arg(ap, void*) );
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            convert_int(intbuf, l, 16/*base*/, False/*unsigned*/, hexcaps);
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len1 = len3 = 0;
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len2 = vex_strlen(intbuf)+2;
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 len3 = ljustify ? fwidth-len2 : 0; }
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PAD(len1); PUT('0'); PUT('x'); PUTSTR(intbuf); PAD(len3);
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case '%': {
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PUT('%');
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* no idea what it is.  Print the format literally and
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               move on. */
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (saved_format <= format) {
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               PUT(*saved_format);
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               saved_format++;
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      format++;
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return nout;
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef PUT
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef PAD
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef PUTSTR
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A general replacement for printf().  Note that only low-level
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   debugging info should be sent via here.  The official route is to
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to use vg_message().  This interface is deprecated.
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar myprintf_buf[1000];
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int   n_myprintf_buf;
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_to_myprintf_buf ( HChar c )
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool emit = toBool(c == '\n' || n_myprintf_buf >= 1000-10 /*paranoia*/);
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   myprintf_buf[n_myprintf_buf++] = c;
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   myprintf_buf[n_myprintf_buf] = 0;
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (emit) {
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (*vex_log_bytes)( myprintf_buf, vex_strlen(myprintf_buf) );
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      n_myprintf_buf = 0;
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      myprintf_buf[n_myprintf_buf] = 0;
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
502436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovUInt vex_printf ( const HChar* format, ... )
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt ret;
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   va_list vargs;
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   va_start(vargs,format);
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n_myprintf_buf = 0;
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   myprintf_buf[n_myprintf_buf] = 0;
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ret = vprintf_wrk ( add_to_myprintf_buf, format, vargs );
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (n_myprintf_buf > 0) {
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (*vex_log_bytes)( myprintf_buf, n_myprintf_buf );
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   va_end(vargs);
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A general replacement for sprintf(). */
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar *vg_sprintf_ptr;
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_to_vg_sprintf_buf ( HChar c )
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *vg_sprintf_ptr++ = c;
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
531436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovUInt vex_sprintf ( HChar* buf, const HChar *format, ... )
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int ret;
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   va_list vargs;
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_sprintf_ptr = buf;
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   va_start(vargs,format);
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ret = vprintf_wrk ( add_to_vg_sprintf_buf, format, vargs );
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   add_to_vg_sprintf_buf(0);
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   va_end(vargs);
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(vex_strlen(buf) == ret);
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                         main_util.c ---*/
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
553