1*1208bc7eSAndroid Build Coastguard Worker #define JEMALLOC_MALLOC_IO_C_
2*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/jemalloc_preamble.h"
3*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/jemalloc_internal_includes.h"
4*1208bc7eSAndroid Build Coastguard Worker
5*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/malloc_io.h"
6*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/util.h"
7*1208bc7eSAndroid Build Coastguard Worker
8*1208bc7eSAndroid Build Coastguard Worker #ifdef assert
9*1208bc7eSAndroid Build Coastguard Worker # undef assert
10*1208bc7eSAndroid Build Coastguard Worker #endif
11*1208bc7eSAndroid Build Coastguard Worker #ifdef not_reached
12*1208bc7eSAndroid Build Coastguard Worker # undef not_reached
13*1208bc7eSAndroid Build Coastguard Worker #endif
14*1208bc7eSAndroid Build Coastguard Worker #ifdef not_implemented
15*1208bc7eSAndroid Build Coastguard Worker # undef not_implemented
16*1208bc7eSAndroid Build Coastguard Worker #endif
17*1208bc7eSAndroid Build Coastguard Worker #ifdef assert_not_implemented
18*1208bc7eSAndroid Build Coastguard Worker # undef assert_not_implemented
19*1208bc7eSAndroid Build Coastguard Worker #endif
20*1208bc7eSAndroid Build Coastguard Worker
21*1208bc7eSAndroid Build Coastguard Worker /*
22*1208bc7eSAndroid Build Coastguard Worker * Define simple versions of assertion macros that won't recurse in case
23*1208bc7eSAndroid Build Coastguard Worker * of assertion failures in malloc_*printf().
24*1208bc7eSAndroid Build Coastguard Worker */
25*1208bc7eSAndroid Build Coastguard Worker #define assert(e) do { \
26*1208bc7eSAndroid Build Coastguard Worker if (config_debug && !(e)) { \
27*1208bc7eSAndroid Build Coastguard Worker malloc_write("<jemalloc>: Failed assertion\n"); \
28*1208bc7eSAndroid Build Coastguard Worker abort(); \
29*1208bc7eSAndroid Build Coastguard Worker } \
30*1208bc7eSAndroid Build Coastguard Worker } while (0)
31*1208bc7eSAndroid Build Coastguard Worker
32*1208bc7eSAndroid Build Coastguard Worker #define not_reached() do { \
33*1208bc7eSAndroid Build Coastguard Worker if (config_debug) { \
34*1208bc7eSAndroid Build Coastguard Worker malloc_write("<jemalloc>: Unreachable code reached\n"); \
35*1208bc7eSAndroid Build Coastguard Worker abort(); \
36*1208bc7eSAndroid Build Coastguard Worker } \
37*1208bc7eSAndroid Build Coastguard Worker unreachable(); \
38*1208bc7eSAndroid Build Coastguard Worker } while (0)
39*1208bc7eSAndroid Build Coastguard Worker
40*1208bc7eSAndroid Build Coastguard Worker #define not_implemented() do { \
41*1208bc7eSAndroid Build Coastguard Worker if (config_debug) { \
42*1208bc7eSAndroid Build Coastguard Worker malloc_write("<jemalloc>: Not implemented\n"); \
43*1208bc7eSAndroid Build Coastguard Worker abort(); \
44*1208bc7eSAndroid Build Coastguard Worker } \
45*1208bc7eSAndroid Build Coastguard Worker } while (0)
46*1208bc7eSAndroid Build Coastguard Worker
47*1208bc7eSAndroid Build Coastguard Worker #define assert_not_implemented(e) do { \
48*1208bc7eSAndroid Build Coastguard Worker if (unlikely(config_debug && !(e))) { \
49*1208bc7eSAndroid Build Coastguard Worker not_implemented(); \
50*1208bc7eSAndroid Build Coastguard Worker } \
51*1208bc7eSAndroid Build Coastguard Worker } while (0)
52*1208bc7eSAndroid Build Coastguard Worker
53*1208bc7eSAndroid Build Coastguard Worker /******************************************************************************/
54*1208bc7eSAndroid Build Coastguard Worker /* Function prototypes for non-inline static functions. */
55*1208bc7eSAndroid Build Coastguard Worker
56*1208bc7eSAndroid Build Coastguard Worker static void wrtmessage(void *cbopaque, const char *s);
57*1208bc7eSAndroid Build Coastguard Worker #define U2S_BUFSIZE ((1U << (LG_SIZEOF_INTMAX_T + 3)) + 1)
58*1208bc7eSAndroid Build Coastguard Worker static char *u2s(uintmax_t x, unsigned base, bool uppercase, char *s,
59*1208bc7eSAndroid Build Coastguard Worker size_t *slen_p);
60*1208bc7eSAndroid Build Coastguard Worker #define D2S_BUFSIZE (1 + U2S_BUFSIZE)
61*1208bc7eSAndroid Build Coastguard Worker static char *d2s(intmax_t x, char sign, char *s, size_t *slen_p);
62*1208bc7eSAndroid Build Coastguard Worker #define O2S_BUFSIZE (1 + U2S_BUFSIZE)
63*1208bc7eSAndroid Build Coastguard Worker static char *o2s(uintmax_t x, bool alt_form, char *s, size_t *slen_p);
64*1208bc7eSAndroid Build Coastguard Worker #define X2S_BUFSIZE (2 + U2S_BUFSIZE)
65*1208bc7eSAndroid Build Coastguard Worker static char *x2s(uintmax_t x, bool alt_form, bool uppercase, char *s,
66*1208bc7eSAndroid Build Coastguard Worker size_t *slen_p);
67*1208bc7eSAndroid Build Coastguard Worker
68*1208bc7eSAndroid Build Coastguard Worker /******************************************************************************/
69*1208bc7eSAndroid Build Coastguard Worker
70*1208bc7eSAndroid Build Coastguard Worker /* malloc_message() setup. */
71*1208bc7eSAndroid Build Coastguard Worker static void
wrtmessage(void * cbopaque,const char * s)72*1208bc7eSAndroid Build Coastguard Worker wrtmessage(void *cbopaque, const char *s) {
73*1208bc7eSAndroid Build Coastguard Worker malloc_write_fd(STDERR_FILENO, s, strlen(s));
74*1208bc7eSAndroid Build Coastguard Worker }
75*1208bc7eSAndroid Build Coastguard Worker
76*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_EXPORT void (*je_malloc_message)(void *, const char *s);
77*1208bc7eSAndroid Build Coastguard Worker
78*1208bc7eSAndroid Build Coastguard Worker /*
79*1208bc7eSAndroid Build Coastguard Worker * Wrapper around malloc_message() that avoids the need for
80*1208bc7eSAndroid Build Coastguard Worker * je_malloc_message(...) throughout the code.
81*1208bc7eSAndroid Build Coastguard Worker */
82*1208bc7eSAndroid Build Coastguard Worker void
malloc_write(const char * s)83*1208bc7eSAndroid Build Coastguard Worker malloc_write(const char *s) {
84*1208bc7eSAndroid Build Coastguard Worker if (je_malloc_message != NULL) {
85*1208bc7eSAndroid Build Coastguard Worker je_malloc_message(NULL, s);
86*1208bc7eSAndroid Build Coastguard Worker } else {
87*1208bc7eSAndroid Build Coastguard Worker wrtmessage(NULL, s);
88*1208bc7eSAndroid Build Coastguard Worker }
89*1208bc7eSAndroid Build Coastguard Worker }
90*1208bc7eSAndroid Build Coastguard Worker
91*1208bc7eSAndroid Build Coastguard Worker /*
92*1208bc7eSAndroid Build Coastguard Worker * glibc provides a non-standard strerror_r() when _GNU_SOURCE is defined, so
93*1208bc7eSAndroid Build Coastguard Worker * provide a wrapper.
94*1208bc7eSAndroid Build Coastguard Worker */
95*1208bc7eSAndroid Build Coastguard Worker int
buferror(int err,char * buf,size_t buflen)96*1208bc7eSAndroid Build Coastguard Worker buferror(int err, char *buf, size_t buflen) {
97*1208bc7eSAndroid Build Coastguard Worker #ifdef _WIN32
98*1208bc7eSAndroid Build Coastguard Worker FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0,
99*1208bc7eSAndroid Build Coastguard Worker (LPSTR)buf, (DWORD)buflen, NULL);
100*1208bc7eSAndroid Build Coastguard Worker return 0;
101*1208bc7eSAndroid Build Coastguard Worker #elif defined(JEMALLOC_STRERROR_R_RETURNS_CHAR_WITH_GNU_SOURCE) && defined(_GNU_SOURCE)
102*1208bc7eSAndroid Build Coastguard Worker char *b = strerror_r(err, buf, buflen);
103*1208bc7eSAndroid Build Coastguard Worker if (b != buf) {
104*1208bc7eSAndroid Build Coastguard Worker strncpy(buf, b, buflen);
105*1208bc7eSAndroid Build Coastguard Worker buf[buflen-1] = '\0';
106*1208bc7eSAndroid Build Coastguard Worker }
107*1208bc7eSAndroid Build Coastguard Worker return 0;
108*1208bc7eSAndroid Build Coastguard Worker #else
109*1208bc7eSAndroid Build Coastguard Worker return strerror_r(err, buf, buflen);
110*1208bc7eSAndroid Build Coastguard Worker #endif
111*1208bc7eSAndroid Build Coastguard Worker }
112*1208bc7eSAndroid Build Coastguard Worker
113*1208bc7eSAndroid Build Coastguard Worker uintmax_t
malloc_strtoumax(const char * restrict nptr,char ** restrict endptr,int base)114*1208bc7eSAndroid Build Coastguard Worker malloc_strtoumax(const char *restrict nptr, char **restrict endptr, int base) {
115*1208bc7eSAndroid Build Coastguard Worker uintmax_t ret, digit;
116*1208bc7eSAndroid Build Coastguard Worker unsigned b;
117*1208bc7eSAndroid Build Coastguard Worker bool neg;
118*1208bc7eSAndroid Build Coastguard Worker const char *p, *ns;
119*1208bc7eSAndroid Build Coastguard Worker
120*1208bc7eSAndroid Build Coastguard Worker p = nptr;
121*1208bc7eSAndroid Build Coastguard Worker if (base < 0 || base == 1 || base > 36) {
122*1208bc7eSAndroid Build Coastguard Worker ns = p;
123*1208bc7eSAndroid Build Coastguard Worker set_errno(EINVAL);
124*1208bc7eSAndroid Build Coastguard Worker ret = UINTMAX_MAX;
125*1208bc7eSAndroid Build Coastguard Worker goto label_return;
126*1208bc7eSAndroid Build Coastguard Worker }
127*1208bc7eSAndroid Build Coastguard Worker b = base;
128*1208bc7eSAndroid Build Coastguard Worker
129*1208bc7eSAndroid Build Coastguard Worker /* Swallow leading whitespace and get sign, if any. */
130*1208bc7eSAndroid Build Coastguard Worker neg = false;
131*1208bc7eSAndroid Build Coastguard Worker while (true) {
132*1208bc7eSAndroid Build Coastguard Worker switch (*p) {
133*1208bc7eSAndroid Build Coastguard Worker case '\t': case '\n': case '\v': case '\f': case '\r': case ' ':
134*1208bc7eSAndroid Build Coastguard Worker p++;
135*1208bc7eSAndroid Build Coastguard Worker break;
136*1208bc7eSAndroid Build Coastguard Worker case '-':
137*1208bc7eSAndroid Build Coastguard Worker neg = true;
138*1208bc7eSAndroid Build Coastguard Worker /* Fall through. */
139*1208bc7eSAndroid Build Coastguard Worker case '+':
140*1208bc7eSAndroid Build Coastguard Worker p++;
141*1208bc7eSAndroid Build Coastguard Worker /* Fall through. */
142*1208bc7eSAndroid Build Coastguard Worker default:
143*1208bc7eSAndroid Build Coastguard Worker goto label_prefix;
144*1208bc7eSAndroid Build Coastguard Worker }
145*1208bc7eSAndroid Build Coastguard Worker }
146*1208bc7eSAndroid Build Coastguard Worker
147*1208bc7eSAndroid Build Coastguard Worker /* Get prefix, if any. */
148*1208bc7eSAndroid Build Coastguard Worker label_prefix:
149*1208bc7eSAndroid Build Coastguard Worker /*
150*1208bc7eSAndroid Build Coastguard Worker * Note where the first non-whitespace/sign character is so that it is
151*1208bc7eSAndroid Build Coastguard Worker * possible to tell whether any digits are consumed (e.g., " 0" vs.
152*1208bc7eSAndroid Build Coastguard Worker * " -x").
153*1208bc7eSAndroid Build Coastguard Worker */
154*1208bc7eSAndroid Build Coastguard Worker ns = p;
155*1208bc7eSAndroid Build Coastguard Worker if (*p == '0') {
156*1208bc7eSAndroid Build Coastguard Worker switch (p[1]) {
157*1208bc7eSAndroid Build Coastguard Worker case '0': case '1': case '2': case '3': case '4': case '5':
158*1208bc7eSAndroid Build Coastguard Worker case '6': case '7':
159*1208bc7eSAndroid Build Coastguard Worker if (b == 0) {
160*1208bc7eSAndroid Build Coastguard Worker b = 8;
161*1208bc7eSAndroid Build Coastguard Worker }
162*1208bc7eSAndroid Build Coastguard Worker if (b == 8) {
163*1208bc7eSAndroid Build Coastguard Worker p++;
164*1208bc7eSAndroid Build Coastguard Worker }
165*1208bc7eSAndroid Build Coastguard Worker break;
166*1208bc7eSAndroid Build Coastguard Worker case 'X': case 'x':
167*1208bc7eSAndroid Build Coastguard Worker switch (p[2]) {
168*1208bc7eSAndroid Build Coastguard Worker case '0': case '1': case '2': case '3': case '4':
169*1208bc7eSAndroid Build Coastguard Worker case '5': case '6': case '7': case '8': case '9':
170*1208bc7eSAndroid Build Coastguard Worker case 'A': case 'B': case 'C': case 'D': case 'E':
171*1208bc7eSAndroid Build Coastguard Worker case 'F':
172*1208bc7eSAndroid Build Coastguard Worker case 'a': case 'b': case 'c': case 'd': case 'e':
173*1208bc7eSAndroid Build Coastguard Worker case 'f':
174*1208bc7eSAndroid Build Coastguard Worker if (b == 0) {
175*1208bc7eSAndroid Build Coastguard Worker b = 16;
176*1208bc7eSAndroid Build Coastguard Worker }
177*1208bc7eSAndroid Build Coastguard Worker if (b == 16) {
178*1208bc7eSAndroid Build Coastguard Worker p += 2;
179*1208bc7eSAndroid Build Coastguard Worker }
180*1208bc7eSAndroid Build Coastguard Worker break;
181*1208bc7eSAndroid Build Coastguard Worker default:
182*1208bc7eSAndroid Build Coastguard Worker break;
183*1208bc7eSAndroid Build Coastguard Worker }
184*1208bc7eSAndroid Build Coastguard Worker break;
185*1208bc7eSAndroid Build Coastguard Worker default:
186*1208bc7eSAndroid Build Coastguard Worker p++;
187*1208bc7eSAndroid Build Coastguard Worker ret = 0;
188*1208bc7eSAndroid Build Coastguard Worker goto label_return;
189*1208bc7eSAndroid Build Coastguard Worker }
190*1208bc7eSAndroid Build Coastguard Worker }
191*1208bc7eSAndroid Build Coastguard Worker if (b == 0) {
192*1208bc7eSAndroid Build Coastguard Worker b = 10;
193*1208bc7eSAndroid Build Coastguard Worker }
194*1208bc7eSAndroid Build Coastguard Worker
195*1208bc7eSAndroid Build Coastguard Worker /* Convert. */
196*1208bc7eSAndroid Build Coastguard Worker ret = 0;
197*1208bc7eSAndroid Build Coastguard Worker while ((*p >= '0' && *p <= '9' && (digit = *p - '0') < b)
198*1208bc7eSAndroid Build Coastguard Worker || (*p >= 'A' && *p <= 'Z' && (digit = 10 + *p - 'A') < b)
199*1208bc7eSAndroid Build Coastguard Worker || (*p >= 'a' && *p <= 'z' && (digit = 10 + *p - 'a') < b)) {
200*1208bc7eSAndroid Build Coastguard Worker uintmax_t pret = ret;
201*1208bc7eSAndroid Build Coastguard Worker ret *= b;
202*1208bc7eSAndroid Build Coastguard Worker ret += digit;
203*1208bc7eSAndroid Build Coastguard Worker if (ret < pret) {
204*1208bc7eSAndroid Build Coastguard Worker /* Overflow. */
205*1208bc7eSAndroid Build Coastguard Worker set_errno(ERANGE);
206*1208bc7eSAndroid Build Coastguard Worker ret = UINTMAX_MAX;
207*1208bc7eSAndroid Build Coastguard Worker goto label_return;
208*1208bc7eSAndroid Build Coastguard Worker }
209*1208bc7eSAndroid Build Coastguard Worker p++;
210*1208bc7eSAndroid Build Coastguard Worker }
211*1208bc7eSAndroid Build Coastguard Worker if (neg) {
212*1208bc7eSAndroid Build Coastguard Worker ret = (uintmax_t)(-((intmax_t)ret));
213*1208bc7eSAndroid Build Coastguard Worker }
214*1208bc7eSAndroid Build Coastguard Worker
215*1208bc7eSAndroid Build Coastguard Worker if (p == ns) {
216*1208bc7eSAndroid Build Coastguard Worker /* No conversion performed. */
217*1208bc7eSAndroid Build Coastguard Worker set_errno(EINVAL);
218*1208bc7eSAndroid Build Coastguard Worker ret = UINTMAX_MAX;
219*1208bc7eSAndroid Build Coastguard Worker goto label_return;
220*1208bc7eSAndroid Build Coastguard Worker }
221*1208bc7eSAndroid Build Coastguard Worker
222*1208bc7eSAndroid Build Coastguard Worker label_return:
223*1208bc7eSAndroid Build Coastguard Worker if (endptr != NULL) {
224*1208bc7eSAndroid Build Coastguard Worker if (p == ns) {
225*1208bc7eSAndroid Build Coastguard Worker /* No characters were converted. */
226*1208bc7eSAndroid Build Coastguard Worker *endptr = (char *)nptr;
227*1208bc7eSAndroid Build Coastguard Worker } else {
228*1208bc7eSAndroid Build Coastguard Worker *endptr = (char *)p;
229*1208bc7eSAndroid Build Coastguard Worker }
230*1208bc7eSAndroid Build Coastguard Worker }
231*1208bc7eSAndroid Build Coastguard Worker return ret;
232*1208bc7eSAndroid Build Coastguard Worker }
233*1208bc7eSAndroid Build Coastguard Worker
234*1208bc7eSAndroid Build Coastguard Worker static char *
u2s(uintmax_t x,unsigned base,bool uppercase,char * s,size_t * slen_p)235*1208bc7eSAndroid Build Coastguard Worker u2s(uintmax_t x, unsigned base, bool uppercase, char *s, size_t *slen_p) {
236*1208bc7eSAndroid Build Coastguard Worker unsigned i;
237*1208bc7eSAndroid Build Coastguard Worker
238*1208bc7eSAndroid Build Coastguard Worker i = U2S_BUFSIZE - 1;
239*1208bc7eSAndroid Build Coastguard Worker s[i] = '\0';
240*1208bc7eSAndroid Build Coastguard Worker switch (base) {
241*1208bc7eSAndroid Build Coastguard Worker case 10:
242*1208bc7eSAndroid Build Coastguard Worker do {
243*1208bc7eSAndroid Build Coastguard Worker i--;
244*1208bc7eSAndroid Build Coastguard Worker s[i] = "0123456789"[x % (uint64_t)10];
245*1208bc7eSAndroid Build Coastguard Worker x /= (uint64_t)10;
246*1208bc7eSAndroid Build Coastguard Worker } while (x > 0);
247*1208bc7eSAndroid Build Coastguard Worker break;
248*1208bc7eSAndroid Build Coastguard Worker case 16: {
249*1208bc7eSAndroid Build Coastguard Worker const char *digits = (uppercase)
250*1208bc7eSAndroid Build Coastguard Worker ? "0123456789ABCDEF"
251*1208bc7eSAndroid Build Coastguard Worker : "0123456789abcdef";
252*1208bc7eSAndroid Build Coastguard Worker
253*1208bc7eSAndroid Build Coastguard Worker do {
254*1208bc7eSAndroid Build Coastguard Worker i--;
255*1208bc7eSAndroid Build Coastguard Worker s[i] = digits[x & 0xf];
256*1208bc7eSAndroid Build Coastguard Worker x >>= 4;
257*1208bc7eSAndroid Build Coastguard Worker } while (x > 0);
258*1208bc7eSAndroid Build Coastguard Worker break;
259*1208bc7eSAndroid Build Coastguard Worker } default: {
260*1208bc7eSAndroid Build Coastguard Worker const char *digits = (uppercase)
261*1208bc7eSAndroid Build Coastguard Worker ? "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
262*1208bc7eSAndroid Build Coastguard Worker : "0123456789abcdefghijklmnopqrstuvwxyz";
263*1208bc7eSAndroid Build Coastguard Worker
264*1208bc7eSAndroid Build Coastguard Worker assert(base >= 2 && base <= 36);
265*1208bc7eSAndroid Build Coastguard Worker do {
266*1208bc7eSAndroid Build Coastguard Worker i--;
267*1208bc7eSAndroid Build Coastguard Worker s[i] = digits[x % (uint64_t)base];
268*1208bc7eSAndroid Build Coastguard Worker x /= (uint64_t)base;
269*1208bc7eSAndroid Build Coastguard Worker } while (x > 0);
270*1208bc7eSAndroid Build Coastguard Worker }}
271*1208bc7eSAndroid Build Coastguard Worker
272*1208bc7eSAndroid Build Coastguard Worker *slen_p = U2S_BUFSIZE - 1 - i;
273*1208bc7eSAndroid Build Coastguard Worker return &s[i];
274*1208bc7eSAndroid Build Coastguard Worker }
275*1208bc7eSAndroid Build Coastguard Worker
276*1208bc7eSAndroid Build Coastguard Worker static char *
d2s(intmax_t x,char sign,char * s,size_t * slen_p)277*1208bc7eSAndroid Build Coastguard Worker d2s(intmax_t x, char sign, char *s, size_t *slen_p) {
278*1208bc7eSAndroid Build Coastguard Worker bool neg;
279*1208bc7eSAndroid Build Coastguard Worker
280*1208bc7eSAndroid Build Coastguard Worker if ((neg = (x < 0))) {
281*1208bc7eSAndroid Build Coastguard Worker x = -x;
282*1208bc7eSAndroid Build Coastguard Worker }
283*1208bc7eSAndroid Build Coastguard Worker s = u2s(x, 10, false, s, slen_p);
284*1208bc7eSAndroid Build Coastguard Worker if (neg) {
285*1208bc7eSAndroid Build Coastguard Worker sign = '-';
286*1208bc7eSAndroid Build Coastguard Worker }
287*1208bc7eSAndroid Build Coastguard Worker switch (sign) {
288*1208bc7eSAndroid Build Coastguard Worker case '-':
289*1208bc7eSAndroid Build Coastguard Worker if (!neg) {
290*1208bc7eSAndroid Build Coastguard Worker break;
291*1208bc7eSAndroid Build Coastguard Worker }
292*1208bc7eSAndroid Build Coastguard Worker /* Fall through. */
293*1208bc7eSAndroid Build Coastguard Worker case ' ':
294*1208bc7eSAndroid Build Coastguard Worker case '+':
295*1208bc7eSAndroid Build Coastguard Worker s--;
296*1208bc7eSAndroid Build Coastguard Worker (*slen_p)++;
297*1208bc7eSAndroid Build Coastguard Worker *s = sign;
298*1208bc7eSAndroid Build Coastguard Worker break;
299*1208bc7eSAndroid Build Coastguard Worker default: not_reached();
300*1208bc7eSAndroid Build Coastguard Worker }
301*1208bc7eSAndroid Build Coastguard Worker return s;
302*1208bc7eSAndroid Build Coastguard Worker }
303*1208bc7eSAndroid Build Coastguard Worker
304*1208bc7eSAndroid Build Coastguard Worker static char *
o2s(uintmax_t x,bool alt_form,char * s,size_t * slen_p)305*1208bc7eSAndroid Build Coastguard Worker o2s(uintmax_t x, bool alt_form, char *s, size_t *slen_p) {
306*1208bc7eSAndroid Build Coastguard Worker s = u2s(x, 8, false, s, slen_p);
307*1208bc7eSAndroid Build Coastguard Worker if (alt_form && *s != '0') {
308*1208bc7eSAndroid Build Coastguard Worker s--;
309*1208bc7eSAndroid Build Coastguard Worker (*slen_p)++;
310*1208bc7eSAndroid Build Coastguard Worker *s = '0';
311*1208bc7eSAndroid Build Coastguard Worker }
312*1208bc7eSAndroid Build Coastguard Worker return s;
313*1208bc7eSAndroid Build Coastguard Worker }
314*1208bc7eSAndroid Build Coastguard Worker
315*1208bc7eSAndroid Build Coastguard Worker static char *
x2s(uintmax_t x,bool alt_form,bool uppercase,char * s,size_t * slen_p)316*1208bc7eSAndroid Build Coastguard Worker x2s(uintmax_t x, bool alt_form, bool uppercase, char *s, size_t *slen_p) {
317*1208bc7eSAndroid Build Coastguard Worker s = u2s(x, 16, uppercase, s, slen_p);
318*1208bc7eSAndroid Build Coastguard Worker if (alt_form) {
319*1208bc7eSAndroid Build Coastguard Worker s -= 2;
320*1208bc7eSAndroid Build Coastguard Worker (*slen_p) += 2;
321*1208bc7eSAndroid Build Coastguard Worker memcpy(s, uppercase ? "0X" : "0x", 2);
322*1208bc7eSAndroid Build Coastguard Worker }
323*1208bc7eSAndroid Build Coastguard Worker return s;
324*1208bc7eSAndroid Build Coastguard Worker }
325*1208bc7eSAndroid Build Coastguard Worker
326*1208bc7eSAndroid Build Coastguard Worker size_t
malloc_vsnprintf(char * str,size_t size,const char * format,va_list ap)327*1208bc7eSAndroid Build Coastguard Worker malloc_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
328*1208bc7eSAndroid Build Coastguard Worker size_t i;
329*1208bc7eSAndroid Build Coastguard Worker const char *f;
330*1208bc7eSAndroid Build Coastguard Worker
331*1208bc7eSAndroid Build Coastguard Worker #define APPEND_C(c) do { \
332*1208bc7eSAndroid Build Coastguard Worker if (i < size) { \
333*1208bc7eSAndroid Build Coastguard Worker str[i] = (c); \
334*1208bc7eSAndroid Build Coastguard Worker } \
335*1208bc7eSAndroid Build Coastguard Worker i++; \
336*1208bc7eSAndroid Build Coastguard Worker } while (0)
337*1208bc7eSAndroid Build Coastguard Worker #define APPEND_S(s, slen) do { \
338*1208bc7eSAndroid Build Coastguard Worker if (i < size) { \
339*1208bc7eSAndroid Build Coastguard Worker size_t cpylen = (slen <= size - i) ? slen : size - i; \
340*1208bc7eSAndroid Build Coastguard Worker memcpy(&str[i], s, cpylen); \
341*1208bc7eSAndroid Build Coastguard Worker } \
342*1208bc7eSAndroid Build Coastguard Worker i += slen; \
343*1208bc7eSAndroid Build Coastguard Worker } while (0)
344*1208bc7eSAndroid Build Coastguard Worker #define APPEND_PADDED_S(s, slen, width, left_justify) do { \
345*1208bc7eSAndroid Build Coastguard Worker /* Left padding. */ \
346*1208bc7eSAndroid Build Coastguard Worker size_t pad_len = (width == -1) ? 0 : ((slen < (size_t)width) ? \
347*1208bc7eSAndroid Build Coastguard Worker (size_t)width - slen : 0); \
348*1208bc7eSAndroid Build Coastguard Worker if (!left_justify && pad_len != 0) { \
349*1208bc7eSAndroid Build Coastguard Worker size_t j; \
350*1208bc7eSAndroid Build Coastguard Worker for (j = 0; j < pad_len; j++) { \
351*1208bc7eSAndroid Build Coastguard Worker APPEND_C(' '); \
352*1208bc7eSAndroid Build Coastguard Worker } \
353*1208bc7eSAndroid Build Coastguard Worker } \
354*1208bc7eSAndroid Build Coastguard Worker /* Value. */ \
355*1208bc7eSAndroid Build Coastguard Worker APPEND_S(s, slen); \
356*1208bc7eSAndroid Build Coastguard Worker /* Right padding. */ \
357*1208bc7eSAndroid Build Coastguard Worker if (left_justify && pad_len != 0) { \
358*1208bc7eSAndroid Build Coastguard Worker size_t j; \
359*1208bc7eSAndroid Build Coastguard Worker for (j = 0; j < pad_len; j++) { \
360*1208bc7eSAndroid Build Coastguard Worker APPEND_C(' '); \
361*1208bc7eSAndroid Build Coastguard Worker } \
362*1208bc7eSAndroid Build Coastguard Worker } \
363*1208bc7eSAndroid Build Coastguard Worker } while (0)
364*1208bc7eSAndroid Build Coastguard Worker #define GET_ARG_NUMERIC(val, len) do { \
365*1208bc7eSAndroid Build Coastguard Worker switch (len) { \
366*1208bc7eSAndroid Build Coastguard Worker case '?': \
367*1208bc7eSAndroid Build Coastguard Worker val = va_arg(ap, int); \
368*1208bc7eSAndroid Build Coastguard Worker break; \
369*1208bc7eSAndroid Build Coastguard Worker case '?' | 0x80: \
370*1208bc7eSAndroid Build Coastguard Worker val = va_arg(ap, unsigned int); \
371*1208bc7eSAndroid Build Coastguard Worker break; \
372*1208bc7eSAndroid Build Coastguard Worker case 'l': \
373*1208bc7eSAndroid Build Coastguard Worker val = va_arg(ap, long); \
374*1208bc7eSAndroid Build Coastguard Worker break; \
375*1208bc7eSAndroid Build Coastguard Worker case 'l' | 0x80: \
376*1208bc7eSAndroid Build Coastguard Worker val = va_arg(ap, unsigned long); \
377*1208bc7eSAndroid Build Coastguard Worker break; \
378*1208bc7eSAndroid Build Coastguard Worker case 'q': \
379*1208bc7eSAndroid Build Coastguard Worker val = va_arg(ap, long long); \
380*1208bc7eSAndroid Build Coastguard Worker break; \
381*1208bc7eSAndroid Build Coastguard Worker case 'q' | 0x80: \
382*1208bc7eSAndroid Build Coastguard Worker val = va_arg(ap, unsigned long long); \
383*1208bc7eSAndroid Build Coastguard Worker break; \
384*1208bc7eSAndroid Build Coastguard Worker case 'j': \
385*1208bc7eSAndroid Build Coastguard Worker val = va_arg(ap, intmax_t); \
386*1208bc7eSAndroid Build Coastguard Worker break; \
387*1208bc7eSAndroid Build Coastguard Worker case 'j' | 0x80: \
388*1208bc7eSAndroid Build Coastguard Worker val = va_arg(ap, uintmax_t); \
389*1208bc7eSAndroid Build Coastguard Worker break; \
390*1208bc7eSAndroid Build Coastguard Worker case 't': \
391*1208bc7eSAndroid Build Coastguard Worker val = va_arg(ap, ptrdiff_t); \
392*1208bc7eSAndroid Build Coastguard Worker break; \
393*1208bc7eSAndroid Build Coastguard Worker case 'z': \
394*1208bc7eSAndroid Build Coastguard Worker val = va_arg(ap, ssize_t); \
395*1208bc7eSAndroid Build Coastguard Worker break; \
396*1208bc7eSAndroid Build Coastguard Worker case 'z' | 0x80: \
397*1208bc7eSAndroid Build Coastguard Worker val = va_arg(ap, size_t); \
398*1208bc7eSAndroid Build Coastguard Worker break; \
399*1208bc7eSAndroid Build Coastguard Worker case 'p': /* Synthetic; used for %p. */ \
400*1208bc7eSAndroid Build Coastguard Worker val = va_arg(ap, uintptr_t); \
401*1208bc7eSAndroid Build Coastguard Worker break; \
402*1208bc7eSAndroid Build Coastguard Worker default: \
403*1208bc7eSAndroid Build Coastguard Worker not_reached(); \
404*1208bc7eSAndroid Build Coastguard Worker val = 0; \
405*1208bc7eSAndroid Build Coastguard Worker } \
406*1208bc7eSAndroid Build Coastguard Worker } while (0)
407*1208bc7eSAndroid Build Coastguard Worker
408*1208bc7eSAndroid Build Coastguard Worker i = 0;
409*1208bc7eSAndroid Build Coastguard Worker f = format;
410*1208bc7eSAndroid Build Coastguard Worker while (true) {
411*1208bc7eSAndroid Build Coastguard Worker switch (*f) {
412*1208bc7eSAndroid Build Coastguard Worker case '\0': goto label_out;
413*1208bc7eSAndroid Build Coastguard Worker case '%': {
414*1208bc7eSAndroid Build Coastguard Worker bool alt_form = false;
415*1208bc7eSAndroid Build Coastguard Worker bool left_justify = false;
416*1208bc7eSAndroid Build Coastguard Worker bool plus_space = false;
417*1208bc7eSAndroid Build Coastguard Worker bool plus_plus = false;
418*1208bc7eSAndroid Build Coastguard Worker int prec = -1;
419*1208bc7eSAndroid Build Coastguard Worker int width = -1;
420*1208bc7eSAndroid Build Coastguard Worker unsigned char len = '?';
421*1208bc7eSAndroid Build Coastguard Worker char *s;
422*1208bc7eSAndroid Build Coastguard Worker size_t slen;
423*1208bc7eSAndroid Build Coastguard Worker
424*1208bc7eSAndroid Build Coastguard Worker f++;
425*1208bc7eSAndroid Build Coastguard Worker /* Flags. */
426*1208bc7eSAndroid Build Coastguard Worker while (true) {
427*1208bc7eSAndroid Build Coastguard Worker switch (*f) {
428*1208bc7eSAndroid Build Coastguard Worker case '#':
429*1208bc7eSAndroid Build Coastguard Worker assert(!alt_form);
430*1208bc7eSAndroid Build Coastguard Worker alt_form = true;
431*1208bc7eSAndroid Build Coastguard Worker break;
432*1208bc7eSAndroid Build Coastguard Worker case '-':
433*1208bc7eSAndroid Build Coastguard Worker assert(!left_justify);
434*1208bc7eSAndroid Build Coastguard Worker left_justify = true;
435*1208bc7eSAndroid Build Coastguard Worker break;
436*1208bc7eSAndroid Build Coastguard Worker case ' ':
437*1208bc7eSAndroid Build Coastguard Worker assert(!plus_space);
438*1208bc7eSAndroid Build Coastguard Worker plus_space = true;
439*1208bc7eSAndroid Build Coastguard Worker break;
440*1208bc7eSAndroid Build Coastguard Worker case '+':
441*1208bc7eSAndroid Build Coastguard Worker assert(!plus_plus);
442*1208bc7eSAndroid Build Coastguard Worker plus_plus = true;
443*1208bc7eSAndroid Build Coastguard Worker break;
444*1208bc7eSAndroid Build Coastguard Worker default: goto label_width;
445*1208bc7eSAndroid Build Coastguard Worker }
446*1208bc7eSAndroid Build Coastguard Worker f++;
447*1208bc7eSAndroid Build Coastguard Worker }
448*1208bc7eSAndroid Build Coastguard Worker /* Width. */
449*1208bc7eSAndroid Build Coastguard Worker label_width:
450*1208bc7eSAndroid Build Coastguard Worker switch (*f) {
451*1208bc7eSAndroid Build Coastguard Worker case '*':
452*1208bc7eSAndroid Build Coastguard Worker width = va_arg(ap, int);
453*1208bc7eSAndroid Build Coastguard Worker f++;
454*1208bc7eSAndroid Build Coastguard Worker if (width < 0) {
455*1208bc7eSAndroid Build Coastguard Worker left_justify = true;
456*1208bc7eSAndroid Build Coastguard Worker width = -width;
457*1208bc7eSAndroid Build Coastguard Worker }
458*1208bc7eSAndroid Build Coastguard Worker break;
459*1208bc7eSAndroid Build Coastguard Worker case '0': case '1': case '2': case '3': case '4':
460*1208bc7eSAndroid Build Coastguard Worker case '5': case '6': case '7': case '8': case '9': {
461*1208bc7eSAndroid Build Coastguard Worker uintmax_t uwidth;
462*1208bc7eSAndroid Build Coastguard Worker set_errno(0);
463*1208bc7eSAndroid Build Coastguard Worker uwidth = malloc_strtoumax(f, (char **)&f, 10);
464*1208bc7eSAndroid Build Coastguard Worker assert(uwidth != UINTMAX_MAX || get_errno() !=
465*1208bc7eSAndroid Build Coastguard Worker ERANGE);
466*1208bc7eSAndroid Build Coastguard Worker width = (int)uwidth;
467*1208bc7eSAndroid Build Coastguard Worker break;
468*1208bc7eSAndroid Build Coastguard Worker } default:
469*1208bc7eSAndroid Build Coastguard Worker break;
470*1208bc7eSAndroid Build Coastguard Worker }
471*1208bc7eSAndroid Build Coastguard Worker /* Width/precision separator. */
472*1208bc7eSAndroid Build Coastguard Worker if (*f == '.') {
473*1208bc7eSAndroid Build Coastguard Worker f++;
474*1208bc7eSAndroid Build Coastguard Worker } else {
475*1208bc7eSAndroid Build Coastguard Worker goto label_length;
476*1208bc7eSAndroid Build Coastguard Worker }
477*1208bc7eSAndroid Build Coastguard Worker /* Precision. */
478*1208bc7eSAndroid Build Coastguard Worker switch (*f) {
479*1208bc7eSAndroid Build Coastguard Worker case '*':
480*1208bc7eSAndroid Build Coastguard Worker prec = va_arg(ap, int);
481*1208bc7eSAndroid Build Coastguard Worker f++;
482*1208bc7eSAndroid Build Coastguard Worker break;
483*1208bc7eSAndroid Build Coastguard Worker case '0': case '1': case '2': case '3': case '4':
484*1208bc7eSAndroid Build Coastguard Worker case '5': case '6': case '7': case '8': case '9': {
485*1208bc7eSAndroid Build Coastguard Worker uintmax_t uprec;
486*1208bc7eSAndroid Build Coastguard Worker set_errno(0);
487*1208bc7eSAndroid Build Coastguard Worker uprec = malloc_strtoumax(f, (char **)&f, 10);
488*1208bc7eSAndroid Build Coastguard Worker assert(uprec != UINTMAX_MAX || get_errno() !=
489*1208bc7eSAndroid Build Coastguard Worker ERANGE);
490*1208bc7eSAndroid Build Coastguard Worker prec = (int)uprec;
491*1208bc7eSAndroid Build Coastguard Worker break;
492*1208bc7eSAndroid Build Coastguard Worker }
493*1208bc7eSAndroid Build Coastguard Worker default: break;
494*1208bc7eSAndroid Build Coastguard Worker }
495*1208bc7eSAndroid Build Coastguard Worker /* Length. */
496*1208bc7eSAndroid Build Coastguard Worker label_length:
497*1208bc7eSAndroid Build Coastguard Worker switch (*f) {
498*1208bc7eSAndroid Build Coastguard Worker case 'l':
499*1208bc7eSAndroid Build Coastguard Worker f++;
500*1208bc7eSAndroid Build Coastguard Worker if (*f == 'l') {
501*1208bc7eSAndroid Build Coastguard Worker len = 'q';
502*1208bc7eSAndroid Build Coastguard Worker f++;
503*1208bc7eSAndroid Build Coastguard Worker } else {
504*1208bc7eSAndroid Build Coastguard Worker len = 'l';
505*1208bc7eSAndroid Build Coastguard Worker }
506*1208bc7eSAndroid Build Coastguard Worker break;
507*1208bc7eSAndroid Build Coastguard Worker case 'q': case 'j': case 't': case 'z':
508*1208bc7eSAndroid Build Coastguard Worker len = *f;
509*1208bc7eSAndroid Build Coastguard Worker f++;
510*1208bc7eSAndroid Build Coastguard Worker break;
511*1208bc7eSAndroid Build Coastguard Worker default: break;
512*1208bc7eSAndroid Build Coastguard Worker }
513*1208bc7eSAndroid Build Coastguard Worker /* Conversion specifier. */
514*1208bc7eSAndroid Build Coastguard Worker switch (*f) {
515*1208bc7eSAndroid Build Coastguard Worker case '%':
516*1208bc7eSAndroid Build Coastguard Worker /* %% */
517*1208bc7eSAndroid Build Coastguard Worker APPEND_C(*f);
518*1208bc7eSAndroid Build Coastguard Worker f++;
519*1208bc7eSAndroid Build Coastguard Worker break;
520*1208bc7eSAndroid Build Coastguard Worker case 'd': case 'i': {
521*1208bc7eSAndroid Build Coastguard Worker intmax_t val JEMALLOC_CC_SILENCE_INIT(0);
522*1208bc7eSAndroid Build Coastguard Worker char buf[D2S_BUFSIZE];
523*1208bc7eSAndroid Build Coastguard Worker
524*1208bc7eSAndroid Build Coastguard Worker GET_ARG_NUMERIC(val, len);
525*1208bc7eSAndroid Build Coastguard Worker s = d2s(val, (plus_plus ? '+' : (plus_space ?
526*1208bc7eSAndroid Build Coastguard Worker ' ' : '-')), buf, &slen);
527*1208bc7eSAndroid Build Coastguard Worker APPEND_PADDED_S(s, slen, width, left_justify);
528*1208bc7eSAndroid Build Coastguard Worker f++;
529*1208bc7eSAndroid Build Coastguard Worker break;
530*1208bc7eSAndroid Build Coastguard Worker } case 'o': {
531*1208bc7eSAndroid Build Coastguard Worker uintmax_t val JEMALLOC_CC_SILENCE_INIT(0);
532*1208bc7eSAndroid Build Coastguard Worker char buf[O2S_BUFSIZE];
533*1208bc7eSAndroid Build Coastguard Worker
534*1208bc7eSAndroid Build Coastguard Worker GET_ARG_NUMERIC(val, len | 0x80);
535*1208bc7eSAndroid Build Coastguard Worker s = o2s(val, alt_form, buf, &slen);
536*1208bc7eSAndroid Build Coastguard Worker APPEND_PADDED_S(s, slen, width, left_justify);
537*1208bc7eSAndroid Build Coastguard Worker f++;
538*1208bc7eSAndroid Build Coastguard Worker break;
539*1208bc7eSAndroid Build Coastguard Worker } case 'u': {
540*1208bc7eSAndroid Build Coastguard Worker uintmax_t val JEMALLOC_CC_SILENCE_INIT(0);
541*1208bc7eSAndroid Build Coastguard Worker char buf[U2S_BUFSIZE];
542*1208bc7eSAndroid Build Coastguard Worker
543*1208bc7eSAndroid Build Coastguard Worker GET_ARG_NUMERIC(val, len | 0x80);
544*1208bc7eSAndroid Build Coastguard Worker s = u2s(val, 10, false, buf, &slen);
545*1208bc7eSAndroid Build Coastguard Worker APPEND_PADDED_S(s, slen, width, left_justify);
546*1208bc7eSAndroid Build Coastguard Worker f++;
547*1208bc7eSAndroid Build Coastguard Worker break;
548*1208bc7eSAndroid Build Coastguard Worker } case 'x': case 'X': {
549*1208bc7eSAndroid Build Coastguard Worker uintmax_t val JEMALLOC_CC_SILENCE_INIT(0);
550*1208bc7eSAndroid Build Coastguard Worker char buf[X2S_BUFSIZE];
551*1208bc7eSAndroid Build Coastguard Worker
552*1208bc7eSAndroid Build Coastguard Worker GET_ARG_NUMERIC(val, len | 0x80);
553*1208bc7eSAndroid Build Coastguard Worker s = x2s(val, alt_form, *f == 'X', buf, &slen);
554*1208bc7eSAndroid Build Coastguard Worker APPEND_PADDED_S(s, slen, width, left_justify);
555*1208bc7eSAndroid Build Coastguard Worker f++;
556*1208bc7eSAndroid Build Coastguard Worker break;
557*1208bc7eSAndroid Build Coastguard Worker } case 'c': {
558*1208bc7eSAndroid Build Coastguard Worker unsigned char val;
559*1208bc7eSAndroid Build Coastguard Worker char buf[2];
560*1208bc7eSAndroid Build Coastguard Worker
561*1208bc7eSAndroid Build Coastguard Worker assert(len == '?' || len == 'l');
562*1208bc7eSAndroid Build Coastguard Worker assert_not_implemented(len != 'l');
563*1208bc7eSAndroid Build Coastguard Worker val = va_arg(ap, int);
564*1208bc7eSAndroid Build Coastguard Worker buf[0] = val;
565*1208bc7eSAndroid Build Coastguard Worker buf[1] = '\0';
566*1208bc7eSAndroid Build Coastguard Worker APPEND_PADDED_S(buf, 1, width, left_justify);
567*1208bc7eSAndroid Build Coastguard Worker f++;
568*1208bc7eSAndroid Build Coastguard Worker break;
569*1208bc7eSAndroid Build Coastguard Worker } case 's':
570*1208bc7eSAndroid Build Coastguard Worker assert(len == '?' || len == 'l');
571*1208bc7eSAndroid Build Coastguard Worker assert_not_implemented(len != 'l');
572*1208bc7eSAndroid Build Coastguard Worker s = va_arg(ap, char *);
573*1208bc7eSAndroid Build Coastguard Worker slen = (prec < 0) ? strlen(s) : (size_t)prec;
574*1208bc7eSAndroid Build Coastguard Worker APPEND_PADDED_S(s, slen, width, left_justify);
575*1208bc7eSAndroid Build Coastguard Worker f++;
576*1208bc7eSAndroid Build Coastguard Worker break;
577*1208bc7eSAndroid Build Coastguard Worker case 'p': {
578*1208bc7eSAndroid Build Coastguard Worker uintmax_t val;
579*1208bc7eSAndroid Build Coastguard Worker char buf[X2S_BUFSIZE];
580*1208bc7eSAndroid Build Coastguard Worker
581*1208bc7eSAndroid Build Coastguard Worker GET_ARG_NUMERIC(val, 'p');
582*1208bc7eSAndroid Build Coastguard Worker s = x2s(val, true, false, buf, &slen);
583*1208bc7eSAndroid Build Coastguard Worker APPEND_PADDED_S(s, slen, width, left_justify);
584*1208bc7eSAndroid Build Coastguard Worker f++;
585*1208bc7eSAndroid Build Coastguard Worker break;
586*1208bc7eSAndroid Build Coastguard Worker } default: not_reached();
587*1208bc7eSAndroid Build Coastguard Worker }
588*1208bc7eSAndroid Build Coastguard Worker break;
589*1208bc7eSAndroid Build Coastguard Worker } default: {
590*1208bc7eSAndroid Build Coastguard Worker APPEND_C(*f);
591*1208bc7eSAndroid Build Coastguard Worker f++;
592*1208bc7eSAndroid Build Coastguard Worker break;
593*1208bc7eSAndroid Build Coastguard Worker }}
594*1208bc7eSAndroid Build Coastguard Worker }
595*1208bc7eSAndroid Build Coastguard Worker label_out:
596*1208bc7eSAndroid Build Coastguard Worker if (i < size) {
597*1208bc7eSAndroid Build Coastguard Worker str[i] = '\0';
598*1208bc7eSAndroid Build Coastguard Worker } else {
599*1208bc7eSAndroid Build Coastguard Worker str[size - 1] = '\0';
600*1208bc7eSAndroid Build Coastguard Worker }
601*1208bc7eSAndroid Build Coastguard Worker
602*1208bc7eSAndroid Build Coastguard Worker #undef APPEND_C
603*1208bc7eSAndroid Build Coastguard Worker #undef APPEND_S
604*1208bc7eSAndroid Build Coastguard Worker #undef APPEND_PADDED_S
605*1208bc7eSAndroid Build Coastguard Worker #undef GET_ARG_NUMERIC
606*1208bc7eSAndroid Build Coastguard Worker return i;
607*1208bc7eSAndroid Build Coastguard Worker }
608*1208bc7eSAndroid Build Coastguard Worker
609*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_FORMAT_PRINTF(3, 4)
610*1208bc7eSAndroid Build Coastguard Worker size_t
malloc_snprintf(char * str,size_t size,const char * format,...)611*1208bc7eSAndroid Build Coastguard Worker malloc_snprintf(char *str, size_t size, const char *format, ...) {
612*1208bc7eSAndroid Build Coastguard Worker size_t ret;
613*1208bc7eSAndroid Build Coastguard Worker va_list ap;
614*1208bc7eSAndroid Build Coastguard Worker
615*1208bc7eSAndroid Build Coastguard Worker va_start(ap, format);
616*1208bc7eSAndroid Build Coastguard Worker ret = malloc_vsnprintf(str, size, format, ap);
617*1208bc7eSAndroid Build Coastguard Worker va_end(ap);
618*1208bc7eSAndroid Build Coastguard Worker
619*1208bc7eSAndroid Build Coastguard Worker return ret;
620*1208bc7eSAndroid Build Coastguard Worker }
621*1208bc7eSAndroid Build Coastguard Worker
622*1208bc7eSAndroid Build Coastguard Worker void
malloc_vcprintf(void (* write_cb)(void *,const char *),void * cbopaque,const char * format,va_list ap)623*1208bc7eSAndroid Build Coastguard Worker malloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque,
624*1208bc7eSAndroid Build Coastguard Worker const char *format, va_list ap) {
625*1208bc7eSAndroid Build Coastguard Worker char buf[MALLOC_PRINTF_BUFSIZE];
626*1208bc7eSAndroid Build Coastguard Worker
627*1208bc7eSAndroid Build Coastguard Worker if (write_cb == NULL) {
628*1208bc7eSAndroid Build Coastguard Worker /*
629*1208bc7eSAndroid Build Coastguard Worker * The caller did not provide an alternate write_cb callback
630*1208bc7eSAndroid Build Coastguard Worker * function, so use the default one. malloc_write() is an
631*1208bc7eSAndroid Build Coastguard Worker * inline function, so use malloc_message() directly here.
632*1208bc7eSAndroid Build Coastguard Worker */
633*1208bc7eSAndroid Build Coastguard Worker write_cb = (je_malloc_message != NULL) ? je_malloc_message :
634*1208bc7eSAndroid Build Coastguard Worker wrtmessage;
635*1208bc7eSAndroid Build Coastguard Worker cbopaque = NULL;
636*1208bc7eSAndroid Build Coastguard Worker }
637*1208bc7eSAndroid Build Coastguard Worker
638*1208bc7eSAndroid Build Coastguard Worker malloc_vsnprintf(buf, sizeof(buf), format, ap);
639*1208bc7eSAndroid Build Coastguard Worker write_cb(cbopaque, buf);
640*1208bc7eSAndroid Build Coastguard Worker }
641*1208bc7eSAndroid Build Coastguard Worker
642*1208bc7eSAndroid Build Coastguard Worker /*
643*1208bc7eSAndroid Build Coastguard Worker * Print to a callback function in such a way as to (hopefully) avoid memory
644*1208bc7eSAndroid Build Coastguard Worker * allocation.
645*1208bc7eSAndroid Build Coastguard Worker */
646*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_FORMAT_PRINTF(3, 4)
647*1208bc7eSAndroid Build Coastguard Worker void
malloc_cprintf(void (* write_cb)(void *,const char *),void * cbopaque,const char * format,...)648*1208bc7eSAndroid Build Coastguard Worker malloc_cprintf(void (*write_cb)(void *, const char *), void *cbopaque,
649*1208bc7eSAndroid Build Coastguard Worker const char *format, ...) {
650*1208bc7eSAndroid Build Coastguard Worker va_list ap;
651*1208bc7eSAndroid Build Coastguard Worker
652*1208bc7eSAndroid Build Coastguard Worker va_start(ap, format);
653*1208bc7eSAndroid Build Coastguard Worker malloc_vcprintf(write_cb, cbopaque, format, ap);
654*1208bc7eSAndroid Build Coastguard Worker va_end(ap);
655*1208bc7eSAndroid Build Coastguard Worker }
656*1208bc7eSAndroid Build Coastguard Worker
657*1208bc7eSAndroid Build Coastguard Worker /* Print to stderr in such a way as to avoid memory allocation. */
658*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_FORMAT_PRINTF(1, 2)
659*1208bc7eSAndroid Build Coastguard Worker void
malloc_printf(const char * format,...)660*1208bc7eSAndroid Build Coastguard Worker malloc_printf(const char *format, ...) {
661*1208bc7eSAndroid Build Coastguard Worker va_list ap;
662*1208bc7eSAndroid Build Coastguard Worker
663*1208bc7eSAndroid Build Coastguard Worker va_start(ap, format);
664*1208bc7eSAndroid Build Coastguard Worker malloc_vcprintf(NULL, NULL, format, ap);
665*1208bc7eSAndroid Build Coastguard Worker va_end(ap);
666*1208bc7eSAndroid Build Coastguard Worker }
667*1208bc7eSAndroid Build Coastguard Worker
668*1208bc7eSAndroid Build Coastguard Worker /*
669*1208bc7eSAndroid Build Coastguard Worker * Restore normal assertion macros, in order to make it possible to compile all
670*1208bc7eSAndroid Build Coastguard Worker * C files as a single concatenation.
671*1208bc7eSAndroid Build Coastguard Worker */
672*1208bc7eSAndroid Build Coastguard Worker #undef assert
673*1208bc7eSAndroid Build Coastguard Worker #undef not_reached
674*1208bc7eSAndroid Build Coastguard Worker #undef not_implemented
675*1208bc7eSAndroid Build Coastguard Worker #undef assert_not_implemented
676*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/assert.h"
677