Blame jemalloc/src/malloc_io.c

Packit 345191
#define JEMALLOC_MALLOC_IO_C_
Packit 345191
#include "jemalloc/internal/jemalloc_preamble.h"
Packit 345191
#include "jemalloc/internal/jemalloc_internal_includes.h"
Packit 345191
Packit 345191
#include "jemalloc/internal/malloc_io.h"
Packit 345191
#include "jemalloc/internal/util.h"
Packit 345191
Packit 345191
#ifdef assert
Packit 345191
#  undef assert
Packit 345191
#endif
Packit 345191
#ifdef not_reached
Packit 345191
#  undef not_reached
Packit 345191
#endif
Packit 345191
#ifdef not_implemented
Packit 345191
#  undef not_implemented
Packit 345191
#endif
Packit 345191
#ifdef assert_not_implemented
Packit 345191
#  undef assert_not_implemented
Packit 345191
#endif
Packit 345191
Packit 345191
/*
Packit 345191
 * Define simple versions of assertion macros that won't recurse in case
Packit 345191
 * of assertion failures in malloc_*printf().
Packit 345191
 */
Packit 345191
#define assert(e) do {							\
Packit 345191
	if (config_debug && !(e)) {					\
Packit 345191
		malloc_write("<jemalloc>: Failed assertion\n");		\
Packit 345191
		abort();						\
Packit 345191
	}								\
Packit 345191
} while (0)
Packit 345191
Packit 345191
#define not_reached() do {						\
Packit 345191
	if (config_debug) {						\
Packit 345191
		malloc_write("<jemalloc>: Unreachable code reached\n");	\
Packit 345191
		abort();						\
Packit 345191
	}								\
Packit 345191
	unreachable();							\
Packit 345191
} while (0)
Packit 345191
Packit 345191
#define not_implemented() do {						\
Packit 345191
	if (config_debug) {						\
Packit 345191
		malloc_write("<jemalloc>: Not implemented\n");		\
Packit 345191
		abort();						\
Packit 345191
	}								\
Packit 345191
} while (0)
Packit 345191
Packit 345191
#define assert_not_implemented(e) do {					\
Packit 345191
	if (unlikely(config_debug && !(e))) {				\
Packit 345191
		not_implemented();					\
Packit 345191
	}								\
Packit 345191
} while (0)
Packit 345191
Packit 345191
/******************************************************************************/
Packit 345191
/* Function prototypes for non-inline static functions. */
Packit 345191
Packit 345191
static void wrtmessage(void *cbopaque, const char *s);
Packit 345191
#define U2S_BUFSIZE ((1U << (LG_SIZEOF_INTMAX_T + 3)) + 1)
Packit 345191
static char *u2s(uintmax_t x, unsigned base, bool uppercase, char *s,
Packit 345191
    size_t *slen_p);
Packit 345191
#define D2S_BUFSIZE (1 + U2S_BUFSIZE)
Packit 345191
static char *d2s(intmax_t x, char sign, char *s, size_t *slen_p);
Packit 345191
#define O2S_BUFSIZE (1 + U2S_BUFSIZE)
Packit 345191
static char *o2s(uintmax_t x, bool alt_form, char *s, size_t *slen_p);
Packit 345191
#define X2S_BUFSIZE (2 + U2S_BUFSIZE)
Packit 345191
static char *x2s(uintmax_t x, bool alt_form, bool uppercase, char *s,
Packit 345191
    size_t *slen_p);
Packit 345191
Packit 345191
/******************************************************************************/
Packit 345191
Packit 345191
/* malloc_message() setup. */
Packit 345191
static void
Packit 345191
wrtmessage(void *cbopaque, const char *s) {
Packit 345191
	malloc_write_fd(STDERR_FILENO, s, strlen(s));
Packit 345191
}
Packit 345191
Packit 345191
JEMALLOC_EXPORT void	(*je_malloc_message)(void *, const char *s);
Packit 345191
Packit 345191
/*
Packit 345191
 * Wrapper around malloc_message() that avoids the need for
Packit 345191
 * je_malloc_message(...) throughout the code.
Packit 345191
 */
Packit 345191
void
Packit 345191
malloc_write(const char *s) {
Packit 345191
	if (je_malloc_message != NULL) {
Packit 345191
		je_malloc_message(NULL, s);
Packit 345191
	} else {
Packit 345191
		wrtmessage(NULL, s);
Packit 345191
	}
Packit 345191
}
Packit 345191
Packit 345191
/*
Packit 345191
 * glibc provides a non-standard strerror_r() when _GNU_SOURCE is defined, so
Packit 345191
 * provide a wrapper.
Packit 345191
 */
Packit 345191
int
Packit 345191
buferror(int err, char *buf, size_t buflen) {
Packit 345191
#ifdef _WIN32
Packit 345191
	FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0,
Packit 345191
	    (LPSTR)buf, (DWORD)buflen, NULL);
Packit 345191
	return 0;
Packit 345191
#elif defined(JEMALLOC_STRERROR_R_RETURNS_CHAR_WITH_GNU_SOURCE) && defined(_GNU_SOURCE)
Packit 345191
	char *b = strerror_r(err, buf, buflen);
Packit 345191
	if (b != buf) {
Packit 345191
		strncpy(buf, b, buflen);
Packit 345191
		buf[buflen-1] = '\0';
Packit 345191
	}
Packit 345191
	return 0;
Packit 345191
#else
Packit 345191
	return strerror_r(err, buf, buflen);
Packit 345191
#endif
Packit 345191
}
Packit 345191
Packit 345191
uintmax_t
Packit 345191
malloc_strtoumax(const char *restrict nptr, char **restrict endptr, int base) {
Packit 345191
	uintmax_t ret, digit;
Packit 345191
	unsigned b;
Packit 345191
	bool neg;
Packit 345191
	const char *p, *ns;
Packit 345191
Packit 345191
	p = nptr;
Packit 345191
	if (base < 0 || base == 1 || base > 36) {
Packit 345191
		ns = p;
Packit 345191
		set_errno(EINVAL);
Packit 345191
		ret = UINTMAX_MAX;
Packit 345191
		goto label_return;
Packit 345191
	}
Packit 345191
	b = base;
Packit 345191
Packit 345191
	/* Swallow leading whitespace and get sign, if any. */
Packit 345191
	neg = false;
Packit 345191
	while (true) {
Packit 345191
		switch (*p) {
Packit 345191
		case '\t': case '\n': case '\v': case '\f': case '\r': case ' ':
Packit 345191
			p++;
Packit 345191
			break;
Packit 345191
		case '-':
Packit 345191
			neg = true;
Packit 345191
			/* Fall through. */
Packit 345191
		case '+':
Packit 345191
			p++;
Packit 345191
			/* Fall through. */
Packit 345191
		default:
Packit 345191
			goto label_prefix;
Packit 345191
		}
Packit 345191
	}
Packit 345191
Packit 345191
	/* Get prefix, if any. */
Packit 345191
	label_prefix:
Packit 345191
	/*
Packit 345191
	 * Note where the first non-whitespace/sign character is so that it is
Packit 345191
	 * possible to tell whether any digits are consumed (e.g., "  0" vs.
Packit 345191
	 * "  -x").
Packit 345191
	 */
Packit 345191
	ns = p;
Packit 345191
	if (*p == '0') {
Packit 345191
		switch (p[1]) {
Packit 345191
		case '0': case '1': case '2': case '3': case '4': case '5':
Packit 345191
		case '6': case '7':
Packit 345191
			if (b == 0) {
Packit 345191
				b = 8;
Packit 345191
			}
Packit 345191
			if (b == 8) {
Packit 345191
				p++;
Packit 345191
			}
Packit 345191
			break;
Packit 345191
		case 'X': case 'x':
Packit 345191
			switch (p[2]) {
Packit 345191
			case '0': case '1': case '2': case '3': case '4':
Packit 345191
			case '5': case '6': case '7': case '8': case '9':
Packit 345191
			case 'A': case 'B': case 'C': case 'D': case 'E':
Packit 345191
			case 'F':
Packit 345191
			case 'a': case 'b': case 'c': case 'd': case 'e':
Packit 345191
			case 'f':
Packit 345191
				if (b == 0) {
Packit 345191
					b = 16;
Packit 345191
				}
Packit 345191
				if (b == 16) {
Packit 345191
					p += 2;
Packit 345191
				}
Packit 345191
				break;
Packit 345191
			default:
Packit 345191
				break;
Packit 345191
			}
Packit 345191
			break;
Packit 345191
		default:
Packit 345191
			p++;
Packit 345191
			ret = 0;
Packit 345191
			goto label_return;
Packit 345191
		}
Packit 345191
	}
Packit 345191
	if (b == 0) {
Packit 345191
		b = 10;
Packit 345191
	}
Packit 345191
Packit 345191
	/* Convert. */
Packit 345191
	ret = 0;
Packit 345191
	while ((*p >= '0' && *p <= '9' && (digit = *p - '0') < b)
Packit 345191
	    || (*p >= 'A' && *p <= 'Z' && (digit = 10 + *p - 'A') < b)
Packit 345191
	    || (*p >= 'a' && *p <= 'z' && (digit = 10 + *p - 'a') < b)) {
Packit 345191
		uintmax_t pret = ret;
Packit 345191
		ret *= b;
Packit 345191
		ret += digit;
Packit 345191
		if (ret < pret) {
Packit 345191
			/* Overflow. */
Packit 345191
			set_errno(ERANGE);
Packit 345191
			ret = UINTMAX_MAX;
Packit 345191
			goto label_return;
Packit 345191
		}
Packit 345191
		p++;
Packit 345191
	}
Packit 345191
	if (neg) {
Packit 345191
		ret = (uintmax_t)(-((intmax_t)ret));
Packit 345191
	}
Packit 345191
Packit 345191
	if (p == ns) {
Packit 345191
		/* No conversion performed. */
Packit 345191
		set_errno(EINVAL);
Packit 345191
		ret = UINTMAX_MAX;
Packit 345191
		goto label_return;
Packit 345191
	}
Packit 345191
Packit 345191
label_return:
Packit 345191
	if (endptr != NULL) {
Packit 345191
		if (p == ns) {
Packit 345191
			/* No characters were converted. */
Packit 345191
			*endptr = (char *)nptr;
Packit 345191
		} else {
Packit 345191
			*endptr = (char *)p;
Packit 345191
		}
Packit 345191
	}
Packit 345191
	return ret;
Packit 345191
}
Packit 345191
Packit 345191
static char *
Packit 345191
u2s(uintmax_t x, unsigned base, bool uppercase, char *s, size_t *slen_p) {
Packit 345191
	unsigned i;
Packit 345191
Packit 345191
	i = U2S_BUFSIZE - 1;
Packit 345191
	s[i] = '\0';
Packit 345191
	switch (base) {
Packit 345191
	case 10:
Packit 345191
		do {
Packit 345191
			i--;
Packit 345191
			s[i] = "0123456789"[x % (uint64_t)10];
Packit 345191
			x /= (uint64_t)10;
Packit 345191
		} while (x > 0);
Packit 345191
		break;
Packit 345191
	case 16: {
Packit 345191
		const char *digits = (uppercase)
Packit 345191
		    ? "0123456789ABCDEF"
Packit 345191
		    : "0123456789abcdef";
Packit 345191
Packit 345191
		do {
Packit 345191
			i--;
Packit 345191
			s[i] = digits[x & 0xf];
Packit 345191
			x >>= 4;
Packit 345191
		} while (x > 0);
Packit 345191
		break;
Packit 345191
	} default: {
Packit 345191
		const char *digits = (uppercase)
Packit 345191
		    ? "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Packit 345191
		    : "0123456789abcdefghijklmnopqrstuvwxyz";
Packit 345191
Packit 345191
		assert(base >= 2 && base <= 36);
Packit 345191
		do {
Packit 345191
			i--;
Packit 345191
			s[i] = digits[x % (uint64_t)base];
Packit 345191
			x /= (uint64_t)base;
Packit 345191
		} while (x > 0);
Packit 345191
	}}
Packit 345191
Packit 345191
	*slen_p = U2S_BUFSIZE - 1 - i;
Packit 345191
	return &s[i];
Packit 345191
}
Packit 345191
Packit 345191
static char *
Packit 345191
d2s(intmax_t x, char sign, char *s, size_t *slen_p) {
Packit 345191
	bool neg;
Packit 345191
Packit 345191
	if ((neg = (x < 0))) {
Packit 345191
		x = -x;
Packit 345191
	}
Packit 345191
	s = u2s(x, 10, false, s, slen_p);
Packit 345191
	if (neg) {
Packit 345191
		sign = '-';
Packit 345191
	}
Packit 345191
	switch (sign) {
Packit 345191
	case '-':
Packit 345191
		if (!neg) {
Packit 345191
			break;
Packit 345191
		}
Packit 345191
		/* Fall through. */
Packit 345191
	case ' ':
Packit 345191
	case '+':
Packit 345191
		s--;
Packit 345191
		(*slen_p)++;
Packit 345191
		*s = sign;
Packit 345191
		break;
Packit 345191
	default: not_reached();
Packit 345191
	}
Packit 345191
	return s;
Packit 345191
}
Packit 345191
Packit 345191
static char *
Packit 345191
o2s(uintmax_t x, bool alt_form, char *s, size_t *slen_p) {
Packit 345191
	s = u2s(x, 8, false, s, slen_p);
Packit 345191
	if (alt_form && *s != '0') {
Packit 345191
		s--;
Packit 345191
		(*slen_p)++;
Packit 345191
		*s = '0';
Packit 345191
	}
Packit 345191
	return s;
Packit 345191
}
Packit 345191
Packit 345191
static char *
Packit 345191
x2s(uintmax_t x, bool alt_form, bool uppercase, char *s, size_t *slen_p) {
Packit 345191
	s = u2s(x, 16, uppercase, s, slen_p);
Packit 345191
	if (alt_form) {
Packit 345191
		s -= 2;
Packit 345191
		(*slen_p) += 2;
Packit 345191
		memcpy(s, uppercase ? "0X" : "0x", 2);
Packit 345191
	}
Packit 345191
	return s;
Packit 345191
}
Packit 345191
Packit 345191
size_t
Packit 345191
malloc_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
Packit 345191
	size_t i;
Packit 345191
	const char *f;
Packit 345191
Packit 345191
#define APPEND_C(c) do {						\
Packit 345191
	if (i < size) {							\
Packit 345191
		str[i] = (c);						\
Packit 345191
	}								\
Packit 345191
	i++;								\
Packit 345191
} while (0)
Packit 345191
#define APPEND_S(s, slen) do {						\
Packit 345191
	if (i < size) {							\
Packit 345191
		size_t cpylen = (slen <= size - i) ? slen : size - i;	\
Packit 345191
		memcpy(&str[i], s, cpylen);				\
Packit 345191
	}								\
Packit 345191
	i += slen;							\
Packit 345191
} while (0)
Packit 345191
#define APPEND_PADDED_S(s, slen, width, left_justify) do {		\
Packit 345191
	/* Left padding. */						\
Packit 345191
	size_t pad_len = (width == -1) ? 0 : ((slen < (size_t)width) ?	\
Packit 345191
	    (size_t)width - slen : 0);					\
Packit 345191
	if (!left_justify && pad_len != 0) {				\
Packit 345191
		size_t j;						\
Packit 345191
		for (j = 0; j < pad_len; j++) {				\
Packit 345191
			APPEND_C(' ');					\
Packit 345191
		}							\
Packit 345191
	}								\
Packit 345191
	/* Value. */							\
Packit 345191
	APPEND_S(s, slen);						\
Packit 345191
	/* Right padding. */						\
Packit 345191
	if (left_justify && pad_len != 0) {				\
Packit 345191
		size_t j;						\
Packit 345191
		for (j = 0; j < pad_len; j++) {				\
Packit 345191
			APPEND_C(' ');					\
Packit 345191
		}							\
Packit 345191
	}								\
Packit 345191
} while (0)
Packit 345191
#define GET_ARG_NUMERIC(val, len) do {					\
Packit 345191
	switch ((unsigned char)len) {					\
Packit 345191
	case '?':							\
Packit 345191
		val = va_arg(ap, int);					\
Packit 345191
		break;							\
Packit 345191
	case '?' | 0x80:						\
Packit 345191
		val = va_arg(ap, unsigned int);				\
Packit 345191
		break;							\
Packit 345191
	case 'l':							\
Packit 345191
		val = va_arg(ap, long);					\
Packit 345191
		break;							\
Packit 345191
	case 'l' | 0x80:						\
Packit 345191
		val = va_arg(ap, unsigned long);			\
Packit 345191
		break;							\
Packit 345191
	case 'q':							\
Packit 345191
		val = va_arg(ap, long long);				\
Packit 345191
		break;							\
Packit 345191
	case 'q' | 0x80:						\
Packit 345191
		val = va_arg(ap, unsigned long long);			\
Packit 345191
		break;							\
Packit 345191
	case 'j':							\
Packit 345191
		val = va_arg(ap, intmax_t);				\
Packit 345191
		break;							\
Packit 345191
	case 'j' | 0x80:						\
Packit 345191
		val = va_arg(ap, uintmax_t);				\
Packit 345191
		break;							\
Packit 345191
	case 't':							\
Packit 345191
		val = va_arg(ap, ptrdiff_t);				\
Packit 345191
		break;							\
Packit 345191
	case 'z':							\
Packit 345191
		val = va_arg(ap, ssize_t);				\
Packit 345191
		break;							\
Packit 345191
	case 'z' | 0x80:						\
Packit 345191
		val = va_arg(ap, size_t);				\
Packit 345191
		break;							\
Packit 345191
	case 'p': /* Synthetic; used for %p. */				\
Packit 345191
		val = va_arg(ap, uintptr_t);				\
Packit 345191
		break;							\
Packit 345191
	default:							\
Packit 345191
		not_reached();						\
Packit 345191
		val = 0;						\
Packit 345191
	}								\
Packit 345191
} while (0)
Packit 345191
Packit 345191
	i = 0;
Packit 345191
	f = format;
Packit 345191
	while (true) {
Packit 345191
		switch (*f) {
Packit 345191
		case '\0': goto label_out;
Packit 345191
		case '%': {
Packit 345191
			bool alt_form = false;
Packit 345191
			bool left_justify = false;
Packit 345191
			bool plus_space = false;
Packit 345191
			bool plus_plus = false;
Packit 345191
			int prec = -1;
Packit 345191
			int width = -1;
Packit 345191
			unsigned char len = '?';
Packit 345191
			char *s;
Packit 345191
			size_t slen;
Packit 345191
Packit 345191
			f++;
Packit 345191
			/* Flags. */
Packit 345191
			while (true) {
Packit 345191
				switch (*f) {
Packit 345191
				case '#':
Packit 345191
					assert(!alt_form);
Packit 345191
					alt_form = true;
Packit 345191
					break;
Packit 345191
				case '-':
Packit 345191
					assert(!left_justify);
Packit 345191
					left_justify = true;
Packit 345191
					break;
Packit 345191
				case ' ':
Packit 345191
					assert(!plus_space);
Packit 345191
					plus_space = true;
Packit 345191
					break;
Packit 345191
				case '+':
Packit 345191
					assert(!plus_plus);
Packit 345191
					plus_plus = true;
Packit 345191
					break;
Packit 345191
				default: goto label_width;
Packit 345191
				}
Packit 345191
				f++;
Packit 345191
			}
Packit 345191
			/* Width. */
Packit 345191
			label_width:
Packit 345191
			switch (*f) {
Packit 345191
			case '*':
Packit 345191
				width = va_arg(ap, int);
Packit 345191
				f++;
Packit 345191
				if (width < 0) {
Packit 345191
					left_justify = true;
Packit 345191
					width = -width;
Packit 345191
				}
Packit 345191
				break;
Packit 345191
			case '0': case '1': case '2': case '3': case '4':
Packit 345191
			case '5': case '6': case '7': case '8': case '9': {
Packit 345191
				uintmax_t uwidth;
Packit 345191
				set_errno(0);
Packit 345191
				uwidth = malloc_strtoumax(f, (char **)&f, 10);
Packit 345191
				assert(uwidth != UINTMAX_MAX || get_errno() !=
Packit 345191
				    ERANGE);
Packit 345191
				width = (int)uwidth;
Packit 345191
				break;
Packit 345191
			} default:
Packit 345191
				break;
Packit 345191
			}
Packit 345191
			/* Width/precision separator. */
Packit 345191
			if (*f == '.') {
Packit 345191
				f++;
Packit 345191
			} else {
Packit 345191
				goto label_length;
Packit 345191
			}
Packit 345191
			/* Precision. */
Packit 345191
			switch (*f) {
Packit 345191
			case '*':
Packit 345191
				prec = va_arg(ap, int);
Packit 345191
				f++;
Packit 345191
				break;
Packit 345191
			case '0': case '1': case '2': case '3': case '4':
Packit 345191
			case '5': case '6': case '7': case '8': case '9': {
Packit 345191
				uintmax_t uprec;
Packit 345191
				set_errno(0);
Packit 345191
				uprec = malloc_strtoumax(f, (char **)&f, 10);
Packit 345191
				assert(uprec != UINTMAX_MAX || get_errno() !=
Packit 345191
				    ERANGE);
Packit 345191
				prec = (int)uprec;
Packit 345191
				break;
Packit 345191
			}
Packit 345191
			default: break;
Packit 345191
			}
Packit 345191
			/* Length. */
Packit 345191
			label_length:
Packit 345191
			switch (*f) {
Packit 345191
			case 'l':
Packit 345191
				f++;
Packit 345191
				if (*f == 'l') {
Packit 345191
					len = 'q';
Packit 345191
					f++;
Packit 345191
				} else {
Packit 345191
					len = 'l';
Packit 345191
				}
Packit 345191
				break;
Packit 345191
			case 'q': case 'j': case 't': case 'z':
Packit 345191
				len = *f;
Packit 345191
				f++;
Packit 345191
				break;
Packit 345191
			default: break;
Packit 345191
			}
Packit 345191
			/* Conversion specifier. */
Packit 345191
			switch (*f) {
Packit 345191
			case '%':
Packit 345191
				/* %% */
Packit 345191
				APPEND_C(*f);
Packit 345191
				f++;
Packit 345191
				break;
Packit 345191
			case 'd': case 'i': {
Packit 345191
				intmax_t val JEMALLOC_CC_SILENCE_INIT(0);
Packit 345191
				char buf[D2S_BUFSIZE];
Packit 345191
Packit 345191
				GET_ARG_NUMERIC(val, len);
Packit 345191
				s = d2s(val, (plus_plus ? '+' : (plus_space ?
Packit 345191
				    ' ' : '-')), buf, &slen);
Packit 345191
				APPEND_PADDED_S(s, slen, width, left_justify);
Packit 345191
				f++;
Packit 345191
				break;
Packit 345191
			} case 'o': {
Packit 345191
				uintmax_t val JEMALLOC_CC_SILENCE_INIT(0);
Packit 345191
				char buf[O2S_BUFSIZE];
Packit 345191
Packit 345191
				GET_ARG_NUMERIC(val, len | 0x80);
Packit 345191
				s = o2s(val, alt_form, buf, &slen);
Packit 345191
				APPEND_PADDED_S(s, slen, width, left_justify);
Packit 345191
				f++;
Packit 345191
				break;
Packit 345191
			} case 'u': {
Packit 345191
				uintmax_t val JEMALLOC_CC_SILENCE_INIT(0);
Packit 345191
				char buf[U2S_BUFSIZE];
Packit 345191
Packit 345191
				GET_ARG_NUMERIC(val, len | 0x80);
Packit 345191
				s = u2s(val, 10, false, buf, &slen);
Packit 345191
				APPEND_PADDED_S(s, slen, width, left_justify);
Packit 345191
				f++;
Packit 345191
				break;
Packit 345191
			} case 'x': case 'X': {
Packit 345191
				uintmax_t val JEMALLOC_CC_SILENCE_INIT(0);
Packit 345191
				char buf[X2S_BUFSIZE];
Packit 345191
Packit 345191
				GET_ARG_NUMERIC(val, len | 0x80);
Packit 345191
				s = x2s(val, alt_form, *f == 'X', buf, &slen);
Packit 345191
				APPEND_PADDED_S(s, slen, width, left_justify);
Packit 345191
				f++;
Packit 345191
				break;
Packit 345191
			} case 'c': {
Packit 345191
				unsigned char val;
Packit 345191
				char buf[2];
Packit 345191
Packit 345191
				assert(len == '?' || len == 'l');
Packit 345191
				assert_not_implemented(len != 'l');
Packit 345191
				val = va_arg(ap, int);
Packit 345191
				buf[0] = val;
Packit 345191
				buf[1] = '\0';
Packit 345191
				APPEND_PADDED_S(buf, 1, width, left_justify);
Packit 345191
				f++;
Packit 345191
				break;
Packit 345191
			} case 's':
Packit 345191
				assert(len == '?' || len == 'l');
Packit 345191
				assert_not_implemented(len != 'l');
Packit 345191
				s = va_arg(ap, char *);
Packit 345191
				slen = (prec < 0) ? strlen(s) : (size_t)prec;
Packit 345191
				APPEND_PADDED_S(s, slen, width, left_justify);
Packit 345191
				f++;
Packit 345191
				break;
Packit 345191
			case 'p': {
Packit 345191
				uintmax_t val;
Packit 345191
				char buf[X2S_BUFSIZE];
Packit 345191
Packit 345191
				GET_ARG_NUMERIC(val, 'p');
Packit 345191
				s = x2s(val, true, false, buf, &slen);
Packit 345191
				APPEND_PADDED_S(s, slen, width, left_justify);
Packit 345191
				f++;
Packit 345191
				break;
Packit 345191
			} default: not_reached();
Packit 345191
			}
Packit 345191
			break;
Packit 345191
		} default: {
Packit 345191
			APPEND_C(*f);
Packit 345191
			f++;
Packit 345191
			break;
Packit 345191
		}}
Packit 345191
	}
Packit 345191
	label_out:
Packit 345191
	if (i < size) {
Packit 345191
		str[i] = '\0';
Packit 345191
	} else {
Packit 345191
		str[size - 1] = '\0';
Packit 345191
	}
Packit 345191
Packit 345191
#undef APPEND_C
Packit 345191
#undef APPEND_S
Packit 345191
#undef APPEND_PADDED_S
Packit 345191
#undef GET_ARG_NUMERIC
Packit 345191
	return i;
Packit 345191
}
Packit 345191
Packit 345191
JEMALLOC_FORMAT_PRINTF(3, 4)
Packit 345191
size_t
Packit 345191
malloc_snprintf(char *str, size_t size, const char *format, ...) {
Packit 345191
	size_t ret;
Packit 345191
	va_list ap;
Packit 345191
Packit 345191
	va_start(ap, format);
Packit 345191
	ret = malloc_vsnprintf(str, size, format, ap);
Packit 345191
	va_end(ap);
Packit 345191
Packit 345191
	return ret;
Packit 345191
}
Packit 345191
Packit 345191
void
Packit 345191
malloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque,
Packit 345191
    const char *format, va_list ap) {
Packit 345191
	char buf[MALLOC_PRINTF_BUFSIZE];
Packit 345191
Packit 345191
	if (write_cb == NULL) {
Packit 345191
		/*
Packit 345191
		 * The caller did not provide an alternate write_cb callback
Packit 345191
		 * function, so use the default one.  malloc_write() is an
Packit 345191
		 * inline function, so use malloc_message() directly here.
Packit 345191
		 */
Packit 345191
		write_cb = (je_malloc_message != NULL) ? je_malloc_message :
Packit 345191
		    wrtmessage;
Packit 345191
	}
Packit 345191
Packit 345191
	malloc_vsnprintf(buf, sizeof(buf), format, ap);
Packit 345191
	write_cb(cbopaque, buf);
Packit 345191
}
Packit 345191
Packit 345191
/*
Packit 345191
 * Print to a callback function in such a way as to (hopefully) avoid memory
Packit 345191
 * allocation.
Packit 345191
 */
Packit 345191
JEMALLOC_FORMAT_PRINTF(3, 4)
Packit 345191
void
Packit 345191
malloc_cprintf(void (*write_cb)(void *, const char *), void *cbopaque,
Packit 345191
    const char *format, ...) {
Packit 345191
	va_list ap;
Packit 345191
Packit 345191
	va_start(ap, format);
Packit 345191
	malloc_vcprintf(write_cb, cbopaque, format, ap);
Packit 345191
	va_end(ap);
Packit 345191
}
Packit 345191
Packit 345191
/* Print to stderr in such a way as to avoid memory allocation. */
Packit 345191
JEMALLOC_FORMAT_PRINTF(1, 2)
Packit 345191
void
Packit 345191
malloc_printf(const char *format, ...) {
Packit 345191
	va_list ap;
Packit 345191
Packit 345191
	va_start(ap, format);
Packit 345191
	malloc_vcprintf(NULL, NULL, format, ap);
Packit 345191
	va_end(ap);
Packit 345191
}
Packit 345191
Packit 345191
/*
Packit 345191
 * Restore normal assertion macros, in order to make it possible to compile all
Packit 345191
 * C files as a single concatenation.
Packit 345191
 */
Packit 345191
#undef assert
Packit 345191
#undef not_reached
Packit 345191
#undef not_implemented
Packit 345191
#undef assert_not_implemented
Packit 345191
#include "jemalloc/internal/assert.h"