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