1f9e3459f751b08b3c2108fda7462827cf8a4f2afJason Evans/*
2f9e3459f751b08b3c2108fda7462827cf8a4f2afJason Evans * Define simple versions of assertion macros that won't recurse in case
3f9e3459f751b08b3c2108fda7462827cf8a4f2afJason Evans * of assertion failures in malloc_*printf().
4f9e3459f751b08b3c2108fda7462827cf8a4f2afJason Evans */
5d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#define	assert(e) do {							\
6d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	if (config_debug && !(e)) {					\
7d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		malloc_write("<jemalloc>: Failed assertion\n");		\
8d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		abort();						\
9d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	}								\
10d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} while (0)
11d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
12d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#define	not_reached() do {						\
13d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	if (config_debug) {						\
14d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		malloc_write("<jemalloc>: Unreachable code reached\n");	\
15d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		abort();						\
16d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	}								\
17d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} while (0)
18d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
19d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#define	not_implemented() do {						\
20d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	if (config_debug) {						\
21d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		malloc_write("<jemalloc>: Not implemented\n");		\
22d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		abort();						\
23d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	}								\
24d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} while (0)
25d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
26d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#define	JEMALLOC_UTIL_C_
27d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#include "jemalloc/internal/jemalloc_internal.h"
28d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
29d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans/******************************************************************************/
30d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans/* Function prototypes for non-inline static functions. */
31d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
32d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansstatic void	wrtmessage(void *cbopaque, const char *s);
33d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#define	U2S_BUFSIZE	((1U << (LG_SIZEOF_INTMAX_T + 3)) + 1)
34d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansstatic char	*u2s(uintmax_t x, unsigned base, bool uppercase, char *s,
35d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans    size_t *slen_p);
36d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#define	D2S_BUFSIZE	(1 + U2S_BUFSIZE)
37d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansstatic char	*d2s(intmax_t x, char sign, char *s, size_t *slen_p);
38d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#define	O2S_BUFSIZE	(1 + U2S_BUFSIZE)
39d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansstatic char	*o2s(uintmax_t x, bool alt_form, char *s, size_t *slen_p);
40d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#define	X2S_BUFSIZE	(2 + U2S_BUFSIZE)
41d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansstatic char	*x2s(uintmax_t x, bool alt_form, bool uppercase, char *s,
42d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans    size_t *slen_p);
43d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
44d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans/******************************************************************************/
45d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
46d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans/* malloc_message() setup. */
47da99e31105eb709ef4ec8a120b115c32a6b9723aMike Hommeystatic void
48d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evanswrtmessage(void *cbopaque, const char *s)
49d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans{
501a0e7770243e0539fa8fef7bb1512f784f93389fMike Hommey
511a0e7770243e0539fa8fef7bb1512f784f93389fMike Hommey#ifdef SYS_write
521a0e7770243e0539fa8fef7bb1512f784f93389fMike Hommey	/*
531a0e7770243e0539fa8fef7bb1512f784f93389fMike Hommey	 * Use syscall(2) rather than write(2) when possible in order to avoid
541a0e7770243e0539fa8fef7bb1512f784f93389fMike Hommey	 * the possibility of memory allocation within libc.  This is necessary
551a0e7770243e0539fa8fef7bb1512f784f93389fMike Hommey	 * on FreeBSD; most operating systems do not have this problem though.
56e42940346e47de63bfc47470c86c3c132ec2db8cChristopher Ferris	 *
57e42940346e47de63bfc47470c86c3c132ec2db8cChristopher Ferris	 * syscall() returns long or int, depending on platform, so capture the
58e42940346e47de63bfc47470c86c3c132ec2db8cChristopher Ferris	 * unused result in the widest plausible type to avoid compiler
59e42940346e47de63bfc47470c86c3c132ec2db8cChristopher Ferris	 * warnings.
601a0e7770243e0539fa8fef7bb1512f784f93389fMike Hommey	 */
61e42940346e47de63bfc47470c86c3c132ec2db8cChristopher Ferris	UNUSED long result = syscall(SYS_write, STDERR_FILENO, s, strlen(s));
621a0e7770243e0539fa8fef7bb1512f784f93389fMike Hommey#else
63e42940346e47de63bfc47470c86c3c132ec2db8cChristopher Ferris	UNUSED ssize_t result = write(STDERR_FILENO, s, strlen(s));
641a0e7770243e0539fa8fef7bb1512f784f93389fMike Hommey#endif
65d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans}
66d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
673597e91482c804592105ea078a0825fdb7c68dffMike HommeyJEMALLOC_EXPORT void	(*je_malloc_message)(void *, const char *s);
68d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
69d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans/*
70889ec59bd3ae3190fb715e64d8d15b6a1b47314aJason Evans * Wrapper around malloc_message() that avoids the need for
71889ec59bd3ae3190fb715e64d8d15b6a1b47314aJason Evans * je_malloc_message(...) throughout the code.
72889ec59bd3ae3190fb715e64d8d15b6a1b47314aJason Evans */
73889ec59bd3ae3190fb715e64d8d15b6a1b47314aJason Evansvoid
74889ec59bd3ae3190fb715e64d8d15b6a1b47314aJason Evansmalloc_write(const char *s)
75889ec59bd3ae3190fb715e64d8d15b6a1b47314aJason Evans{
76889ec59bd3ae3190fb715e64d8d15b6a1b47314aJason Evans
773597e91482c804592105ea078a0825fdb7c68dffMike Hommey	if (je_malloc_message != NULL)
783597e91482c804592105ea078a0825fdb7c68dffMike Hommey		je_malloc_message(NULL, s);
793597e91482c804592105ea078a0825fdb7c68dffMike Hommey	else
803597e91482c804592105ea078a0825fdb7c68dffMike Hommey		wrtmessage(NULL, s);
81889ec59bd3ae3190fb715e64d8d15b6a1b47314aJason Evans}
82889ec59bd3ae3190fb715e64d8d15b6a1b47314aJason Evans
83889ec59bd3ae3190fb715e64d8d15b6a1b47314aJason Evans/*
84d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans * glibc provides a non-standard strerror_r() when _GNU_SOURCE is defined, so
85d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans * provide a wrapper.
86d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans */
87d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansint
882a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evansbuferror(int err, char *buf, size_t buflen)
89d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans{
90a19e87fbad020e8dd3d26682032929e8e5ae71c1Mike Hommey
91a19e87fbad020e8dd3d26682032929e8e5ae71c1Mike Hommey#ifdef _WIN32
92f69e2f6fdab40c7612be5fd69960b8c7d40dba44Mike Hommey	FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0,
93e42940346e47de63bfc47470c86c3c132ec2db8cChristopher Ferris	    (LPSTR)buf, (DWORD)buflen, NULL);
94a19e87fbad020e8dd3d26682032929e8e5ae71c1Mike Hommey	return (0);
95008267b9f6a0e4d92a78f0e8c0697248020fc8d3Felix Janda#elif defined(__GLIBC__) && defined(_GNU_SOURCE)
962a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	char *b = strerror_r(err, buf, buflen);
97d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	if (b != buf) {
98d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		strncpy(buf, b, buflen);
99d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		buf[buflen-1] = '\0';
100d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	}
101d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	return (0);
102d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#else
1032a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	return (strerror_r(err, buf, buflen));
104d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#endif
105d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans}
106d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
10741b6afb834b1f5250223678c52bd4f013d4234f6Jason Evansuintmax_t
108e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evansmalloc_strtoumax(const char *restrict nptr, char **restrict endptr, int base)
10941b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans{
11041b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	uintmax_t ret, digit;
1113e310b34eb53eb331981ecda2ea5f10cf6956747Chris Peterson	unsigned b;
11241b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	bool neg;
11341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	const char *p, *ns;
11441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans
115e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans	p = nptr;
11641b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	if (base < 0 || base == 1 || base > 36) {
117e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans		ns = p;
118a14bce85e885f83c96116cc5438ae52d740f3727Mike Hommey		set_errno(EINVAL);
119e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans		ret = UINTMAX_MAX;
120e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans		goto label_return;
12141b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	}
12241b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	b = base;
12341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans
12441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	/* Swallow leading whitespace and get sign, if any. */
12541b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	neg = false;
12641b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	while (true) {
12741b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans		switch (*p) {
12841b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans		case '\t': case '\n': case '\v': case '\f': case '\r': case ' ':
12941b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			p++;
13041b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			break;
13141b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans		case '-':
13241b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			neg = true;
13341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			/* Fall through. */
13441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans		case '+':
13541b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			p++;
13641b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			/* Fall through. */
13741b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans		default:
138a1ee7838e14b321a97bfacb1f1cf5004198f2203Jason Evans			goto label_prefix;
13941b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans		}
14041b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	}
14141b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans
14241b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	/* Get prefix, if any. */
143a1ee7838e14b321a97bfacb1f1cf5004198f2203Jason Evans	label_prefix:
14441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	/*
14541b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	 * Note where the first non-whitespace/sign character is so that it is
14641b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	 * possible to tell whether any digits are consumed (e.g., "  0" vs.
14741b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	 * "  -x").
14841b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	 */
14941b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	ns = p;
15041b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	if (*p == '0') {
15141b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans		switch (p[1]) {
15241b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans		case '0': case '1': case '2': case '3': case '4': case '5':
15341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans		case '6': case '7':
15441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			if (b == 0)
15541b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans				b = 8;
15641b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			if (b == 8)
15741b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans				p++;
15841b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			break;
159e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans		case 'X': case 'x':
16041b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			switch (p[2]) {
16141b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			case '0': case '1': case '2': case '3': case '4':
16241b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			case '5': case '6': case '7': case '8': case '9':
16341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			case 'A': case 'B': case 'C': case 'D': case 'E':
16441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			case 'F':
16541b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			case 'a': case 'b': case 'c': case 'd': case 'e':
16641b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			case 'f':
16741b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans				if (b == 0)
16841b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans					b = 16;
16941b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans				if (b == 16)
17041b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans					p += 2;
17141b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans				break;
17241b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			default:
17341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans				break;
17441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			}
17541b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			break;
17641b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans		default:
177e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans			p++;
178e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans			ret = 0;
179e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans			goto label_return;
18041b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans		}
18141b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	}
18241b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	if (b == 0)
18341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans		b = 10;
18441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans
18541b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	/* Convert. */
18641b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	ret = 0;
18741b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	while ((*p >= '0' && *p <= '9' && (digit = *p - '0') < b)
18841b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	    || (*p >= 'A' && *p <= 'Z' && (digit = 10 + *p - 'A') < b)
18941b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	    || (*p >= 'a' && *p <= 'z' && (digit = 10 + *p - 'a') < b)) {
19041b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans		uintmax_t pret = ret;
19141b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans		ret *= b;
19241b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans		ret += digit;
19341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans		if (ret < pret) {
19441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			/* Overflow. */
195a14bce85e885f83c96116cc5438ae52d740f3727Mike Hommey			set_errno(ERANGE);
196e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans			ret = UINTMAX_MAX;
197e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans			goto label_return;
19841b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans		}
19941b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans		p++;
20041b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	}
20141b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	if (neg)
20241b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans		ret = -ret;
20341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans
204e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans	if (p == ns) {
205e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans		/* No conversion performed. */
206e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans		set_errno(EINVAL);
207e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans		ret = UINTMAX_MAX;
208e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans		goto label_return;
209e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans	}
210e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans
211e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evanslabel_return:
21241b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	if (endptr != NULL) {
21341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans		if (p == ns) {
21441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			/* No characters were converted. */
21541b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			*endptr = (char *)nptr;
21641b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans		} else
21741b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans			*endptr = (char *)p;
21841b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	}
21941b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans	return (ret);
22041b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans}
22141b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans
222d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansstatic char *
223d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansu2s(uintmax_t x, unsigned base, bool uppercase, char *s, size_t *slen_p)
224d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans{
225d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	unsigned i;
226d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
227d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	i = U2S_BUFSIZE - 1;
228d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	s[i] = '\0';
229d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	switch (base) {
230d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	case 10:
231d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		do {
232d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			i--;
233d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			s[i] = "0123456789"[x % (uint64_t)10];
234d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			x /= (uint64_t)10;
235d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		} while (x > 0);
236d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		break;
237d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	case 16: {
238d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		const char *digits = (uppercase)
239d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		    ? "0123456789ABCDEF"
240d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		    : "0123456789abcdef";
241d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
242d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		do {
243d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			i--;
244d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			s[i] = digits[x & 0xf];
245d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			x >>= 4;
246d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		} while (x > 0);
247d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		break;
248d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	} default: {
249d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		const char *digits = (uppercase)
250d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		    ? "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
251d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		    : "0123456789abcdefghijklmnopqrstuvwxyz";
252d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
253d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		assert(base >= 2 && base <= 36);
254d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		do {
255d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			i--;
256d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			s[i] = digits[x % (uint64_t)base];
257d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			x /= (uint64_t)base;
258d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		} while (x > 0);
259d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	}}
260d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
261d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	*slen_p = U2S_BUFSIZE - 1 - i;
262d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	return (&s[i]);
263d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans}
264d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
265d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansstatic char *
266d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansd2s(intmax_t x, char sign, char *s, size_t *slen_p)
267d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans{
268d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	bool neg;
269d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
270d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	if ((neg = (x < 0)))
271d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		x = -x;
272d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	s = u2s(x, 10, false, s, slen_p);
273d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	if (neg)
274d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		sign = '-';
275d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	switch (sign) {
276d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	case '-':
277551ebc43647521bdd0bc78558b106762b3388928Jason Evans		if (!neg)
278d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			break;
279d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		/* Fall through. */
280d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	case ' ':
281d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	case '+':
282d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		s--;
283d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		(*slen_p)++;
284d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		*s = sign;
285d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		break;
286d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	default: not_reached();
287d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	}
288d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	return (s);
289d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans}
290d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
291d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansstatic char *
292d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evanso2s(uintmax_t x, bool alt_form, char *s, size_t *slen_p)
293d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans{
294d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
295d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	s = u2s(x, 8, false, s, slen_p);
296d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	if (alt_form && *s != '0') {
297d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		s--;
298d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		(*slen_p)++;
299d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		*s = '0';
300d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	}
301d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	return (s);
302d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans}
303d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
304d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansstatic char *
305d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansx2s(uintmax_t x, bool alt_form, bool uppercase, char *s, size_t *slen_p)
306d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans{
307d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
308d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	s = u2s(x, 16, uppercase, s, slen_p);
309d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	if (alt_form) {
310d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		s -= 2;
311d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		(*slen_p) += 2;
312d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		memcpy(s, uppercase ? "0X" : "0x", 2);
313d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	}
314d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	return (s);
315d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans}
316d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
317d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansint
318d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansmalloc_vsnprintf(char *str, size_t size, const char *format, va_list ap)
319d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans{
320d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	int ret;
321d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	size_t i;
322d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	const char *f;
323d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
324d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#define	APPEND_C(c) do {						\
325d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	if (i < size)							\
326d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		str[i] = (c);						\
327d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	i++;								\
328d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} while (0)
329d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#define	APPEND_S(s, slen) do {						\
330d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	if (i < size) {							\
331d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		size_t cpylen = (slen <= size - i) ? slen : size - i;	\
332d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		memcpy(&str[i], s, cpylen);				\
333d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	}								\
334d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	i += slen;							\
335d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} while (0)
336d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#define	APPEND_PADDED_S(s, slen, width, left_justify) do {		\
337d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	/* Left padding. */						\
338d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	size_t pad_len = (width == -1) ? 0 : ((slen < (size_t)width) ?	\
339d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	    (size_t)width - slen : 0);					\
340551ebc43647521bdd0bc78558b106762b3388928Jason Evans	if (!left_justify && pad_len != 0) {				\
341d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		size_t j;						\
342d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		for (j = 0; j < pad_len; j++)				\
343d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			APPEND_C(' ');					\
344d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	}								\
345d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	/* Value. */							\
346d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	APPEND_S(s, slen);						\
347d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	/* Right padding. */						\
348d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	if (left_justify && pad_len != 0) {				\
349d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		size_t j;						\
350d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		for (j = 0; j < pad_len; j++)				\
351d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			APPEND_C(' ');					\
352d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	}								\
353d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} while (0)
354a4f124f59fa5f702231432a7e5fa45140ba81e2aJason Evans#define	GET_ARG_NUMERIC(val, len) do {					\
355d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	switch (len) {							\
356d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	case '?':							\
357d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		val = va_arg(ap, int);					\
358d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		break;							\
3591ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey	case '?' | 0x80:						\
3601ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey		val = va_arg(ap, unsigned int);				\
3611ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey		break;							\
362d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	case 'l':							\
363d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		val = va_arg(ap, long);					\
364d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		break;							\
3651ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey	case 'l' | 0x80:						\
3661ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey		val = va_arg(ap, unsigned long);			\
3671ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey		break;							\
368d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	case 'q':							\
369d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		val = va_arg(ap, long long);				\
370d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		break;							\
3711ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey	case 'q' | 0x80:						\
3721ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey		val = va_arg(ap, unsigned long long);			\
3731ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey		break;							\
374d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	case 'j':							\
375d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		val = va_arg(ap, intmax_t);				\
376d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		break;							\
377e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans	case 'j' | 0x80:						\
378e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans		val = va_arg(ap, uintmax_t);				\
379e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans		break;							\
380d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	case 't':							\
381d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		val = va_arg(ap, ptrdiff_t);				\
382d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		break;							\
383d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	case 'z':							\
38441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans		val = va_arg(ap, ssize_t);				\
385d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		break;							\
3861ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey	case 'z' | 0x80:						\
3871ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey		val = va_arg(ap, size_t);				\
3881ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey		break;							\
389cd9a1346e96f71bdecdc654ea50fc62d76371e74Jason Evans	case 'p': /* Synthetic; used for %p. */				\
390cd9a1346e96f71bdecdc654ea50fc62d76371e74Jason Evans		val = va_arg(ap, uintptr_t);				\
391cd9a1346e96f71bdecdc654ea50fc62d76371e74Jason Evans		break;							\
39270807bc54b06bb259b6607541af44bc73a890bf6Chris Peterson	default:							\
39370807bc54b06bb259b6607541af44bc73a890bf6Chris Peterson		not_reached();						\
39470807bc54b06bb259b6607541af44bc73a890bf6Chris Peterson		val = 0;						\
395d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	}								\
396d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} while (0)
397d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
398d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	i = 0;
399d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	f = format;
400d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	while (true) {
401d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		switch (*f) {
402a1ee7838e14b321a97bfacb1f1cf5004198f2203Jason Evans		case '\0': goto label_out;
403d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		case '%': {
404d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			bool alt_form = false;
405d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			bool left_justify = false;
406d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			bool plus_space = false;
407d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			bool plus_plus = false;
408d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			int prec = -1;
409d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			int width = -1;
4101ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey			unsigned char len = '?';
411d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
412d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			f++;
413d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			/* Flags. */
414d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			while (true) {
415d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				switch (*f) {
416d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				case '#':
417551ebc43647521bdd0bc78558b106762b3388928Jason Evans					assert(!alt_form);
418d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans					alt_form = true;
419d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans					break;
420d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				case '-':
421551ebc43647521bdd0bc78558b106762b3388928Jason Evans					assert(!left_justify);
422d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans					left_justify = true;
423d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans					break;
424d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				case ' ':
425551ebc43647521bdd0bc78558b106762b3388928Jason Evans					assert(!plus_space);
426d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans					plus_space = true;
427d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans					break;
428d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				case '+':
429551ebc43647521bdd0bc78558b106762b3388928Jason Evans					assert(!plus_plus);
430d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans					plus_plus = true;
431d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans					break;
432a1ee7838e14b321a97bfacb1f1cf5004198f2203Jason Evans				default: goto label_width;
433d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				}
434d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				f++;
435d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			}
436d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			/* Width. */
437a1ee7838e14b321a97bfacb1f1cf5004198f2203Jason Evans			label_width:
438d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			switch (*f) {
439d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			case '*':
440d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				width = va_arg(ap, int);
441d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				f++;
442e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans				if (width < 0) {
443e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans					left_justify = true;
444e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans					width = -width;
445e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans				}
446d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				break;
447d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			case '0': case '1': case '2': case '3': case '4':
448d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			case '5': case '6': case '7': case '8': case '9': {
44941b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans				uintmax_t uwidth;
450a14bce85e885f83c96116cc5438ae52d740f3727Mike Hommey				set_errno(0);
45141b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans				uwidth = malloc_strtoumax(f, (char **)&f, 10);
452a14bce85e885f83c96116cc5438ae52d740f3727Mike Hommey				assert(uwidth != UINTMAX_MAX || get_errno() !=
45341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans				    ERANGE);
454d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				width = (int)uwidth;
455d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				break;
456e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans			} default:
457e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans				break;
458d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			}
459e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans			/* Width/precision separator. */
460e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans			if (*f == '.')
461e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans				f++;
462e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans			else
463e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans				goto label_length;
464d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			/* Precision. */
465d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			switch (*f) {
466d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			case '*':
467d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				prec = va_arg(ap, int);
468d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				f++;
469d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				break;
470d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			case '0': case '1': case '2': case '3': case '4':
471d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			case '5': case '6': case '7': case '8': case '9': {
47241b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans				uintmax_t uprec;
473a14bce85e885f83c96116cc5438ae52d740f3727Mike Hommey				set_errno(0);
47441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans				uprec = malloc_strtoumax(f, (char **)&f, 10);
475a14bce85e885f83c96116cc5438ae52d740f3727Mike Hommey				assert(uprec != UINTMAX_MAX || get_errno() !=
476a14bce85e885f83c96116cc5438ae52d740f3727Mike Hommey				    ERANGE);
477d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				prec = (int)uprec;
478d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				break;
479d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			}
480d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			default: break;
481d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			}
482d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			/* Length. */
483a1ee7838e14b321a97bfacb1f1cf5004198f2203Jason Evans			label_length:
484d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			switch (*f) {
485d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			case 'l':
486d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				f++;
487d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				if (*f == 'l') {
488d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans					len = 'q';
489d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans					f++;
490d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				} else
491d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans					len = 'l';
492d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				break;
493e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans			case 'q': case 'j': case 't': case 'z':
494e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans				len = *f;
495d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				f++;
496d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				break;
497d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			default: break;
498d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			}
499d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			/* Conversion specifier. */
500d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			switch (*f) {
501d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				char *s;
502d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				size_t slen;
5030c4e743eaf2ab6bcfd56e002fb82f95801b9292eJason Evans			case '%':
5040c4e743eaf2ab6bcfd56e002fb82f95801b9292eJason Evans				/* %% */
5050c4e743eaf2ab6bcfd56e002fb82f95801b9292eJason Evans				APPEND_C(*f);
5060c4e743eaf2ab6bcfd56e002fb82f95801b9292eJason Evans				f++;
5070c4e743eaf2ab6bcfd56e002fb82f95801b9292eJason Evans				break;
508d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			case 'd': case 'i': {
5099225a1991a58190207cca2ff3cdba966bb322dd5Jason Evans				intmax_t val JEMALLOC_CC_SILENCE_INIT(0);
510d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				char buf[D2S_BUFSIZE];
511d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
512d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				GET_ARG_NUMERIC(val, len);
513d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				s = d2s(val, (plus_plus ? '+' : (plus_space ?
514d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				    ' ' : '-')), buf, &slen);
515d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				APPEND_PADDED_S(s, slen, width, left_justify);
516d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				f++;
517d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				break;
518d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			} case 'o': {
5199225a1991a58190207cca2ff3cdba966bb322dd5Jason Evans				uintmax_t val JEMALLOC_CC_SILENCE_INIT(0);
520d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				char buf[O2S_BUFSIZE];
521d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
5221ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey				GET_ARG_NUMERIC(val, len | 0x80);
523d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				s = o2s(val, alt_form, buf, &slen);
524d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				APPEND_PADDED_S(s, slen, width, left_justify);
525d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				f++;
526d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				break;
527d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			} case 'u': {
5289225a1991a58190207cca2ff3cdba966bb322dd5Jason Evans				uintmax_t val JEMALLOC_CC_SILENCE_INIT(0);
529d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				char buf[U2S_BUFSIZE];
530d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
5311ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey				GET_ARG_NUMERIC(val, len | 0x80);
532d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				s = u2s(val, 10, false, buf, &slen);
533d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				APPEND_PADDED_S(s, slen, width, left_justify);
534d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				f++;
535d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				break;
536d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			} case 'x': case 'X': {
5379225a1991a58190207cca2ff3cdba966bb322dd5Jason Evans				uintmax_t val JEMALLOC_CC_SILENCE_INIT(0);
538d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				char buf[X2S_BUFSIZE];
539d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
5401ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey				GET_ARG_NUMERIC(val, len | 0x80);
541d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				s = x2s(val, alt_form, *f == 'X', buf, &slen);
542d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				APPEND_PADDED_S(s, slen, width, left_justify);
543d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				f++;
544d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				break;
545d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			} case 'c': {
546d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				unsigned char val;
547d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				char buf[2];
548d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
549d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				assert(len == '?' || len == 'l');
550d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				assert_not_implemented(len != 'l');
551d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				val = va_arg(ap, int);
552d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				buf[0] = val;
553d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				buf[1] = '\0';
554d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				APPEND_PADDED_S(buf, 1, width, left_justify);
555d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				f++;
556d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				break;
557d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			} case 's':
558d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				assert(len == '?' || len == 'l');
559d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				assert_not_implemented(len != 'l');
560d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				s = va_arg(ap, char *);
5613e310b34eb53eb331981ecda2ea5f10cf6956747Chris Peterson				slen = (prec < 0) ? strlen(s) : (size_t)prec;
562d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				APPEND_PADDED_S(s, slen, width, left_justify);
563d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				f++;
564d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				break;
565d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			case 'p': {
566d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				uintmax_t val;
567d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				char buf[X2S_BUFSIZE];
568d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
569cd9a1346e96f71bdecdc654ea50fc62d76371e74Jason Evans				GET_ARG_NUMERIC(val, 'p');
570d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				s = x2s(val, true, false, buf, &slen);
571d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				APPEND_PADDED_S(s, slen, width, left_justify);
572d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				f++;
573d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans				break;
5740c4e743eaf2ab6bcfd56e002fb82f95801b9292eJason Evans			} default: not_reached();
575d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			}
576d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			break;
577d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		} default: {
578d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			APPEND_C(*f);
579d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			f++;
580d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans			break;
581d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		}}
582d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	}
583a1ee7838e14b321a97bfacb1f1cf5004198f2203Jason Evans	label_out:
584d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	if (i < size)
585d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		str[i] = '\0';
586d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	else
587d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		str[size - 1] = '\0';
588e42940346e47de63bfc47470c86c3c132ec2db8cChristopher Ferris	assert(i < INT_MAX);
589e42940346e47de63bfc47470c86c3c132ec2db8cChristopher Ferris	ret = (int)i;
590d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
591d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#undef APPEND_C
592d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#undef APPEND_S
593d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#undef APPEND_PADDED_S
594d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#undef GET_ARG_NUMERIC
595d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	return (ret);
596d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans}
597d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
598e42c309eba6c5084dc0abda9b211e91e2c548fdfJason EvansJEMALLOC_FORMAT_PRINTF(3, 4)
599d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansint
600d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansmalloc_snprintf(char *str, size_t size, const char *format, ...)
601d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans{
602d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	int ret;
603d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	va_list ap;
604d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
605d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	va_start(ap, format);
606d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	ret = malloc_vsnprintf(str, size, format, ap);
607d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	va_end(ap);
608d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
609d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	return (ret);
610d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans}
611d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
612d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansvoid
613d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansmalloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque,
614d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans    const char *format, va_list ap)
615d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans{
616cd9a1346e96f71bdecdc654ea50fc62d76371e74Jason Evans	char buf[MALLOC_PRINTF_BUFSIZE];
617d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
618d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	if (write_cb == NULL) {
619d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		/*
620d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		 * The caller did not provide an alternate write_cb callback
621d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		 * function, so use the default one.  malloc_write() is an
622d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		 * inline function, so use malloc_message() directly here.
623d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		 */
6243597e91482c804592105ea078a0825fdb7c68dffMike Hommey		write_cb = (je_malloc_message != NULL) ? je_malloc_message :
6253597e91482c804592105ea078a0825fdb7c68dffMike Hommey		    wrtmessage;
626d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans		cbopaque = NULL;
627d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	}
628d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
629cd9a1346e96f71bdecdc654ea50fc62d76371e74Jason Evans	malloc_vsnprintf(buf, sizeof(buf), format, ap);
630cd9a1346e96f71bdecdc654ea50fc62d76371e74Jason Evans	write_cb(cbopaque, buf);
631d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans}
632d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
633d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans/*
634d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans * Print to a callback function in such a way as to (hopefully) avoid memory
635d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans * allocation.
636d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans */
637e42c309eba6c5084dc0abda9b211e91e2c548fdfJason EvansJEMALLOC_FORMAT_PRINTF(3, 4)
638d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansvoid
639d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansmalloc_cprintf(void (*write_cb)(void *, const char *), void *cbopaque,
640d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans    const char *format, ...)
641d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans{
642d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	va_list ap;
643d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
644d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	va_start(ap, format);
645d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	malloc_vcprintf(write_cb, cbopaque, format, ap);
646d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	va_end(ap);
647d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans}
648d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
649d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans/* Print to stderr in such a way as to avoid memory allocation. */
650e42c309eba6c5084dc0abda9b211e91e2c548fdfJason EvansJEMALLOC_FORMAT_PRINTF(1, 2)
651d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansvoid
652d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansmalloc_printf(const char *format, ...)
653d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans{
654d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	va_list ap;
655d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans
656d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	va_start(ap, format);
657d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	malloc_vcprintf(NULL, NULL, format, ap);
658d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans	va_end(ap);
659d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans}
660f9e3459f751b08b3c2108fda7462827cf8a4f2afJason Evans
661f9e3459f751b08b3c2108fda7462827cf8a4f2afJason Evans/*
662f9e3459f751b08b3c2108fda7462827cf8a4f2afJason Evans * Restore normal assertion macros, in order to make it possible to compile all
663f9e3459f751b08b3c2108fda7462827cf8a4f2afJason Evans * C files as a single concatenation.
664f9e3459f751b08b3c2108fda7462827cf8a4f2afJason Evans */
665f9e3459f751b08b3c2108fda7462827cf8a4f2afJason Evans#undef assert
666f9e3459f751b08b3c2108fda7462827cf8a4f2afJason Evans#undef not_reached
667f9e3459f751b08b3c2108fda7462827cf8a4f2afJason Evans#undef not_implemented
668f9e3459f751b08b3c2108fda7462827cf8a4f2afJason Evans#include "jemalloc/internal/assert.h"
669