xref: /aosp_15_r20/external/jemalloc_new/src/malloc_io.c (revision 1208bc7e437ced7eb82efac44ba17e3beba411da)
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