util.c revision 338c9bf92ebf4e196bc9bbaf845b85b66ee2c77b
1d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#define assert(e) do { \ 2d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans if (config_debug && !(e)) { \ 3d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans malloc_write("<jemalloc>: Failed assertion\n"); \ 4d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans abort(); \ 5d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } \ 6d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} while (0) 7d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 8d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#define not_reached() do { \ 9d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans if (config_debug) { \ 10d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans malloc_write("<jemalloc>: Unreachable code reached\n"); \ 11d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans abort(); \ 12d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } \ 13d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} while (0) 14d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 15d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#define not_implemented() do { \ 16d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans if (config_debug) { \ 17d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans malloc_write("<jemalloc>: Not implemented\n"); \ 18d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans abort(); \ 19d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } \ 20d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} while (0) 21d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 22d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#define JEMALLOC_UTIL_C_ 23d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#include "jemalloc/internal/jemalloc_internal.h" 24d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 25d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans/******************************************************************************/ 26d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans/* Function prototypes for non-inline static functions. */ 27d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 28d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansstatic void wrtmessage(void *cbopaque, const char *s); 29d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#define U2S_BUFSIZE ((1U << (LG_SIZEOF_INTMAX_T + 3)) + 1) 30d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansstatic char *u2s(uintmax_t x, unsigned base, bool uppercase, char *s, 31d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans size_t *slen_p); 32d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#define D2S_BUFSIZE (1 + U2S_BUFSIZE) 33d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansstatic char *d2s(intmax_t x, char sign, char *s, size_t *slen_p); 34d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#define O2S_BUFSIZE (1 + U2S_BUFSIZE) 35d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansstatic char *o2s(uintmax_t x, bool alt_form, char *s, size_t *slen_p); 36d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#define X2S_BUFSIZE (2 + U2S_BUFSIZE) 37d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansstatic char *x2s(uintmax_t x, bool alt_form, bool uppercase, char *s, 38d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans size_t *slen_p); 39d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 40d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans/******************************************************************************/ 41d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 42d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans/* malloc_message() setup. */ 43da99e31105eb709ef4ec8a120b115c32a6b9723aMike Hommeystatic void 44d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evanswrtmessage(void *cbopaque, const char *s) 45d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans{ 461a0e7770243e0539fa8fef7bb1512f784f93389fMike Hommey 471a0e7770243e0539fa8fef7bb1512f784f93389fMike Hommey#ifdef SYS_write 481a0e7770243e0539fa8fef7bb1512f784f93389fMike Hommey /* 491a0e7770243e0539fa8fef7bb1512f784f93389fMike Hommey * Use syscall(2) rather than write(2) when possible in order to avoid 501a0e7770243e0539fa8fef7bb1512f784f93389fMike Hommey * the possibility of memory allocation within libc. This is necessary 511a0e7770243e0539fa8fef7bb1512f784f93389fMike Hommey * on FreeBSD; most operating systems do not have this problem though. 521a0e7770243e0539fa8fef7bb1512f784f93389fMike Hommey */ 5341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans UNUSED int result = syscall(SYS_write, STDERR_FILENO, s, strlen(s)); 541a0e7770243e0539fa8fef7bb1512f784f93389fMike Hommey#else 551a0e7770243e0539fa8fef7bb1512f784f93389fMike Hommey UNUSED int result = write(STDERR_FILENO, s, strlen(s)); 561a0e7770243e0539fa8fef7bb1512f784f93389fMike Hommey#endif 57d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} 58d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 593597e91482c804592105ea078a0825fdb7c68dffMike HommeyJEMALLOC_EXPORT void (*je_malloc_message)(void *, const char *s); 60d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 61d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans/* 62889ec59bd3ae3190fb715e64d8d15b6a1b47314aJason Evans * Wrapper around malloc_message() that avoids the need for 63889ec59bd3ae3190fb715e64d8d15b6a1b47314aJason Evans * je_malloc_message(...) throughout the code. 64889ec59bd3ae3190fb715e64d8d15b6a1b47314aJason Evans */ 65889ec59bd3ae3190fb715e64d8d15b6a1b47314aJason Evansvoid 66889ec59bd3ae3190fb715e64d8d15b6a1b47314aJason Evansmalloc_write(const char *s) 67889ec59bd3ae3190fb715e64d8d15b6a1b47314aJason Evans{ 68889ec59bd3ae3190fb715e64d8d15b6a1b47314aJason Evans 693597e91482c804592105ea078a0825fdb7c68dffMike Hommey if (je_malloc_message != NULL) 703597e91482c804592105ea078a0825fdb7c68dffMike Hommey je_malloc_message(NULL, s); 713597e91482c804592105ea078a0825fdb7c68dffMike Hommey else 723597e91482c804592105ea078a0825fdb7c68dffMike Hommey wrtmessage(NULL, s); 73889ec59bd3ae3190fb715e64d8d15b6a1b47314aJason Evans} 74889ec59bd3ae3190fb715e64d8d15b6a1b47314aJason Evans 75889ec59bd3ae3190fb715e64d8d15b6a1b47314aJason Evans/* 76d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans * glibc provides a non-standard strerror_r() when _GNU_SOURCE is defined, so 77d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans * provide a wrapper. 78d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans */ 79d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansint 802a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evansbuferror(int err, char *buf, size_t buflen) 81d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans{ 82a19e87fbad020e8dd3d26682032929e8e5ae71c1Mike Hommey 83a19e87fbad020e8dd3d26682032929e8e5ae71c1Mike Hommey#ifdef _WIN32 84a19e87fbad020e8dd3d26682032929e8e5ae71c1Mike Hommey FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, 85a19e87fbad020e8dd3d26682032929e8e5ae71c1Mike Hommey (LPSTR)buf, buflen, NULL); 86a19e87fbad020e8dd3d26682032929e8e5ae71c1Mike Hommey return (0); 87a19e87fbad020e8dd3d26682032929e8e5ae71c1Mike Hommey#elif defined(_GNU_SOURCE) 882a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans char *b = strerror_r(err, buf, buflen); 89d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans if (b != buf) { 90d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans strncpy(buf, b, buflen); 91d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans buf[buflen-1] = '\0'; 92d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } 93d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans return (0); 94d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#else 952a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans return (strerror_r(err, buf, buflen)); 96d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#endif 97d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} 98d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 9941b6afb834b1f5250223678c52bd4f013d4234f6Jason Evansuintmax_t 100e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evansmalloc_strtoumax(const char *restrict nptr, char **restrict endptr, int base) 10141b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans{ 10241b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans uintmax_t ret, digit; 103932d77dc8089af14d4d334188aa800d405fc51f6Chris Peterson unsigned b; 10441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans bool neg; 10541b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans const char *p, *ns; 10641b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans 107e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans p = nptr; 10841b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans if (base < 0 || base == 1 || base > 36) { 109e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans ns = p; 110a14bce85e885f83c96116cc5438ae52d740f3727Mike Hommey set_errno(EINVAL); 111e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans ret = UINTMAX_MAX; 112e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans goto label_return; 11341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans } 11441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans b = base; 11541b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans 11641b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans /* Swallow leading whitespace and get sign, if any. */ 11741b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans neg = false; 11841b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans while (true) { 11941b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans switch (*p) { 12041b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans case '\t': case '\n': case '\v': case '\f': case '\r': case ' ': 12141b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans p++; 12241b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans break; 12341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans case '-': 12441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans neg = true; 12541b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans /* Fall through. */ 12641b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans case '+': 12741b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans p++; 12841b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans /* Fall through. */ 12941b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans default: 130a1ee7838e14b321a97bfacb1f1cf5004198f2203Jason Evans goto label_prefix; 13141b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans } 13241b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans } 13341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans 13441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans /* Get prefix, if any. */ 135a1ee7838e14b321a97bfacb1f1cf5004198f2203Jason Evans label_prefix: 13641b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans /* 13741b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans * Note where the first non-whitespace/sign character is so that it is 13841b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans * possible to tell whether any digits are consumed (e.g., " 0" vs. 13941b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans * " -x"). 14041b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans */ 14141b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans ns = p; 14241b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans if (*p == '0') { 14341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans switch (p[1]) { 14441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans case '0': case '1': case '2': case '3': case '4': case '5': 14541b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans case '6': case '7': 14641b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans if (b == 0) 14741b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans b = 8; 14841b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans if (b == 8) 14941b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans p++; 15041b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans break; 151e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans case 'X': case 'x': 15241b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans switch (p[2]) { 15341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans case '0': case '1': case '2': case '3': case '4': 15441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans case '5': case '6': case '7': case '8': case '9': 15541b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans case 'A': case 'B': case 'C': case 'D': case 'E': 15641b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans case 'F': 15741b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans case 'a': case 'b': case 'c': case 'd': case 'e': 15841b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans case 'f': 15941b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans if (b == 0) 16041b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans b = 16; 16141b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans if (b == 16) 16241b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans p += 2; 16341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans break; 16441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans default: 16541b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans break; 16641b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans } 16741b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans break; 16841b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans default: 169e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans p++; 170e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans ret = 0; 171e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans goto label_return; 17241b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans } 17341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans } 17441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans if (b == 0) 17541b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans b = 10; 17641b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans 17741b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans /* Convert. */ 17841b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans ret = 0; 17941b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans while ((*p >= '0' && *p <= '9' && (digit = *p - '0') < b) 18041b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans || (*p >= 'A' && *p <= 'Z' && (digit = 10 + *p - 'A') < b) 18141b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans || (*p >= 'a' && *p <= 'z' && (digit = 10 + *p - 'a') < b)) { 18241b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans uintmax_t pret = ret; 18341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans ret *= b; 18441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans ret += digit; 18541b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans if (ret < pret) { 18641b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans /* Overflow. */ 187a14bce85e885f83c96116cc5438ae52d740f3727Mike Hommey set_errno(ERANGE); 188e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans ret = UINTMAX_MAX; 189e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans goto label_return; 19041b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans } 19141b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans p++; 19241b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans } 19341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans if (neg) 19441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans ret = -ret; 19541b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans 196e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans if (p == ns) { 197e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans /* No conversion performed. */ 198e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans set_errno(EINVAL); 199e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans ret = UINTMAX_MAX; 200e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans goto label_return; 201e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans } 202e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans 203e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evanslabel_return: 20441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans if (endptr != NULL) { 20541b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans if (p == ns) { 20641b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans /* No characters were converted. */ 20741b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans *endptr = (char *)nptr; 20841b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans } else 20941b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans *endptr = (char *)p; 21041b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans } 21141b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans return (ret); 21241b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans} 21341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans 214d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansstatic char * 215d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansu2s(uintmax_t x, unsigned base, bool uppercase, char *s, size_t *slen_p) 216d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans{ 217d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans unsigned i; 218d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 219d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans i = U2S_BUFSIZE - 1; 220d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans s[i] = '\0'; 221d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans switch (base) { 222d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case 10: 223d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans do { 224d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans i--; 225d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans s[i] = "0123456789"[x % (uint64_t)10]; 226d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans x /= (uint64_t)10; 227d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } while (x > 0); 228d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 229d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case 16: { 230d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans const char *digits = (uppercase) 231d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans ? "0123456789ABCDEF" 232d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans : "0123456789abcdef"; 233d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 234d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans do { 235d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans i--; 236d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans s[i] = digits[x & 0xf]; 237d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans x >>= 4; 238d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } while (x > 0); 239d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 240d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } default: { 241d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans const char *digits = (uppercase) 242d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans ? "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" 243d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans : "0123456789abcdefghijklmnopqrstuvwxyz"; 244d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 245d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans assert(base >= 2 && base <= 36); 246d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans do { 247d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans i--; 248d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans s[i] = digits[x % (uint64_t)base]; 249d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans x /= (uint64_t)base; 250d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } while (x > 0); 251d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans }} 252d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 253d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans *slen_p = U2S_BUFSIZE - 1 - i; 254d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans return (&s[i]); 255d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} 256d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 257d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansstatic char * 258d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansd2s(intmax_t x, char sign, char *s, size_t *slen_p) 259d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans{ 260d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans bool neg; 261d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 262d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans if ((neg = (x < 0))) 263d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans x = -x; 264d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans s = u2s(x, 10, false, s, slen_p); 265d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans if (neg) 266d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans sign = '-'; 267d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans switch (sign) { 268d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case '-': 269d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans if (neg == false) 270d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 271d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans /* Fall through. */ 272d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case ' ': 273d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case '+': 274d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans s--; 275d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans (*slen_p)++; 276d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans *s = sign; 277d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 278d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans default: not_reached(); 279d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } 280d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans return (s); 281d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} 282d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 283d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansstatic char * 284d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evanso2s(uintmax_t x, bool alt_form, char *s, size_t *slen_p) 285d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans{ 286d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 287d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans s = u2s(x, 8, false, s, slen_p); 288d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans if (alt_form && *s != '0') { 289d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans s--; 290d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans (*slen_p)++; 291d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans *s = '0'; 292d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } 293d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans return (s); 294d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} 295d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 296d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansstatic char * 297d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansx2s(uintmax_t x, bool alt_form, bool uppercase, char *s, size_t *slen_p) 298d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans{ 299d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 300d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans s = u2s(x, 16, uppercase, s, slen_p); 301d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans if (alt_form) { 302d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans s -= 2; 303d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans (*slen_p) += 2; 304d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans memcpy(s, uppercase ? "0X" : "0x", 2); 305d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } 306d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans return (s); 307d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} 308d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 309d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansint 310d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansmalloc_vsnprintf(char *str, size_t size, const char *format, va_list ap) 311d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans{ 312d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans int ret; 313d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans size_t i; 314d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans const char *f; 315d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 316d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#define APPEND_C(c) do { \ 317d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans if (i < size) \ 318d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans str[i] = (c); \ 319d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans i++; \ 320d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} while (0) 321d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#define APPEND_S(s, slen) do { \ 322d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans if (i < size) { \ 323d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans size_t cpylen = (slen <= size - i) ? slen : size - i; \ 324d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans memcpy(&str[i], s, cpylen); \ 325d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } \ 326d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans i += slen; \ 327d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} while (0) 328d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#define APPEND_PADDED_S(s, slen, width, left_justify) do { \ 329d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans /* Left padding. */ \ 330d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans size_t pad_len = (width == -1) ? 0 : ((slen < (size_t)width) ? \ 331d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans (size_t)width - slen : 0); \ 332d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans if (left_justify == false && pad_len != 0) { \ 333d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans size_t j; \ 334d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans for (j = 0; j < pad_len; j++) \ 335d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans APPEND_C(' '); \ 336d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } \ 337d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans /* Value. */ \ 338d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans APPEND_S(s, slen); \ 339d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans /* Right padding. */ \ 340d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason 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} while (0) 346a4f124f59fa5f702231432a7e5fa45140ba81e2aJason Evans#define GET_ARG_NUMERIC(val, len) do { \ 347d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans switch (len) { \ 348d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case '?': \ 349d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans val = va_arg(ap, int); \ 350d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; \ 3511ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey case '?' | 0x80: \ 3521ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey val = va_arg(ap, unsigned int); \ 3531ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey break; \ 354d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case 'l': \ 355d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans val = va_arg(ap, long); \ 356d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; \ 3571ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey case 'l' | 0x80: \ 3581ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey val = va_arg(ap, unsigned long); \ 3591ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey break; \ 360d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case 'q': \ 361d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans val = va_arg(ap, long long); \ 362d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; \ 3631ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey case 'q' | 0x80: \ 3641ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey val = va_arg(ap, unsigned long long); \ 3651ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey break; \ 366d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case 'j': \ 367d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans val = va_arg(ap, intmax_t); \ 368d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; \ 369e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans case 'j' | 0x80: \ 370e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans val = va_arg(ap, uintmax_t); \ 371e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans break; \ 372d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case 't': \ 373d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans val = va_arg(ap, ptrdiff_t); \ 374d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; \ 375d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case 'z': \ 37641b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans val = va_arg(ap, ssize_t); \ 377d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; \ 3781ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey case 'z' | 0x80: \ 3791ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey val = va_arg(ap, size_t); \ 3801ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey break; \ 381cd9a1346e96f71bdecdc654ea50fc62d76371e74Jason Evans case 'p': /* Synthetic; used for %p. */ \ 382cd9a1346e96f71bdecdc654ea50fc62d76371e74Jason Evans val = va_arg(ap, uintptr_t); \ 383cd9a1346e96f71bdecdc654ea50fc62d76371e74Jason Evans break; \ 384338c9bf92ebf4e196bc9bbaf845b85b66ee2c77bChris Peterson default: \ 385338c9bf92ebf4e196bc9bbaf845b85b66ee2c77bChris Peterson not_reached(); \ 386338c9bf92ebf4e196bc9bbaf845b85b66ee2c77bChris Peterson val = 0; \ 387d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } \ 388d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} while (0) 389d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 390d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans i = 0; 391d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans f = format; 392d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans while (true) { 393d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans switch (*f) { 394a1ee7838e14b321a97bfacb1f1cf5004198f2203Jason Evans case '\0': goto label_out; 395d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case '%': { 396d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans bool alt_form = false; 397d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans bool left_justify = false; 398d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans bool plus_space = false; 399d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans bool plus_plus = false; 400d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans int prec = -1; 401d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans int width = -1; 4021ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey unsigned char len = '?'; 403d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 404d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans f++; 405d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans /* Flags. */ 406d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans while (true) { 407d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans switch (*f) { 408d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case '#': 409d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans assert(alt_form == false); 410d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans alt_form = true; 411d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 412d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case '-': 413d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans assert(left_justify == false); 414d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans left_justify = true; 415d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 416d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case ' ': 417d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans assert(plus_space == false); 418d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans plus_space = true; 419d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 420d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case '+': 421d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans assert(plus_plus == false); 422d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans plus_plus = true; 423d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 424a1ee7838e14b321a97bfacb1f1cf5004198f2203Jason Evans default: goto label_width; 425d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } 426d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans f++; 427d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } 428d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans /* Width. */ 429a1ee7838e14b321a97bfacb1f1cf5004198f2203Jason Evans label_width: 430d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans switch (*f) { 431d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case '*': 432d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans width = va_arg(ap, int); 433d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans f++; 434e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans if (width < 0) { 435e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans left_justify = true; 436e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans width = -width; 437e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans } 438d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 439d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case '0': case '1': case '2': case '3': case '4': 440d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case '5': case '6': case '7': case '8': case '9': { 44141b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans uintmax_t uwidth; 442a14bce85e885f83c96116cc5438ae52d740f3727Mike Hommey set_errno(0); 44341b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans uwidth = malloc_strtoumax(f, (char **)&f, 10); 444a14bce85e885f83c96116cc5438ae52d740f3727Mike Hommey assert(uwidth != UINTMAX_MAX || get_errno() != 44541b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans ERANGE); 446d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans width = (int)uwidth; 447d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 448e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans } default: 449e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans break; 450d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } 451e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans /* Width/precision separator. */ 452e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans if (*f == '.') 453e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans f++; 454e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans else 455e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans goto label_length; 456d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans /* Precision. */ 457d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans switch (*f) { 458d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case '*': 459d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans prec = va_arg(ap, int); 460d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans f++; 461d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 462d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case '0': case '1': case '2': case '3': case '4': 463d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case '5': case '6': case '7': case '8': case '9': { 46441b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans uintmax_t uprec; 465a14bce85e885f83c96116cc5438ae52d740f3727Mike Hommey set_errno(0); 46641b6afb834b1f5250223678c52bd4f013d4234f6Jason Evans uprec = malloc_strtoumax(f, (char **)&f, 10); 467a14bce85e885f83c96116cc5438ae52d740f3727Mike Hommey assert(uprec != UINTMAX_MAX || get_errno() != 468a14bce85e885f83c96116cc5438ae52d740f3727Mike Hommey ERANGE); 469d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans prec = (int)uprec; 470d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 471d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } 472d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans default: break; 473d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } 474d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans /* Length. */ 475a1ee7838e14b321a97bfacb1f1cf5004198f2203Jason Evans label_length: 476d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans switch (*f) { 477d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case 'l': 478d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans f++; 479d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans if (*f == 'l') { 480d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans len = 'q'; 481d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans f++; 482d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } else 483d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans len = 'l'; 484d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 485e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans case 'q': case 'j': case 't': case 'z': 486e18c25d23de0e845f0ee7e11d02c1be044738a3cJason Evans len = *f; 487d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans f++; 488d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 489d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans default: break; 490d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } 491d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans /* Conversion specifier. */ 492d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans switch (*f) { 493d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans char *s; 494d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans size_t slen; 4950c4e743eaf2ab6bcfd56e002fb82f95801b9292eJason Evans case '%': 4960c4e743eaf2ab6bcfd56e002fb82f95801b9292eJason Evans /* %% */ 4970c4e743eaf2ab6bcfd56e002fb82f95801b9292eJason Evans APPEND_C(*f); 4980c4e743eaf2ab6bcfd56e002fb82f95801b9292eJason Evans f++; 4990c4e743eaf2ab6bcfd56e002fb82f95801b9292eJason Evans break; 500d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case 'd': case 'i': { 5019225a1991a58190207cca2ff3cdba966bb322dd5Jason Evans intmax_t val JEMALLOC_CC_SILENCE_INIT(0); 502d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans char buf[D2S_BUFSIZE]; 503d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 504d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans GET_ARG_NUMERIC(val, len); 505d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans s = d2s(val, (plus_plus ? '+' : (plus_space ? 506d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans ' ' : '-')), buf, &slen); 507d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans APPEND_PADDED_S(s, slen, width, left_justify); 508d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans f++; 509d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 510d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } case 'o': { 5119225a1991a58190207cca2ff3cdba966bb322dd5Jason Evans uintmax_t val JEMALLOC_CC_SILENCE_INIT(0); 512d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans char buf[O2S_BUFSIZE]; 513d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 5141ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey GET_ARG_NUMERIC(val, len | 0x80); 515d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans s = o2s(val, alt_form, buf, &slen); 516d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans APPEND_PADDED_S(s, slen, width, left_justify); 517d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans f++; 518d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 519d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } case 'u': { 5209225a1991a58190207cca2ff3cdba966bb322dd5Jason Evans uintmax_t val JEMALLOC_CC_SILENCE_INIT(0); 521d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans char buf[U2S_BUFSIZE]; 522d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 5231ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey GET_ARG_NUMERIC(val, len | 0x80); 524d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans s = u2s(val, 10, false, buf, &slen); 525d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans APPEND_PADDED_S(s, slen, width, left_justify); 526d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans f++; 527d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 528d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } case 'x': case 'X': { 5299225a1991a58190207cca2ff3cdba966bb322dd5Jason Evans uintmax_t val JEMALLOC_CC_SILENCE_INIT(0); 530d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans char buf[X2S_BUFSIZE]; 531d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 5321ad56385adc40cfbca1b14c240a9c647135ac641Mike Hommey GET_ARG_NUMERIC(val, len | 0x80); 533d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans s = x2s(val, alt_form, *f == 'X', buf, &slen); 534d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans APPEND_PADDED_S(s, slen, width, left_justify); 535d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans f++; 536d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 537d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } case 'c': { 538d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans unsigned char val; 539d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans char buf[2]; 540d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 541d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans assert(len == '?' || len == 'l'); 542d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans assert_not_implemented(len != 'l'); 543d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans val = va_arg(ap, int); 544d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans buf[0] = val; 545d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans buf[1] = '\0'; 546d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans APPEND_PADDED_S(buf, 1, width, left_justify); 547d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans f++; 548d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 549d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } case 's': 550d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans assert(len == '?' || len == 'l'); 551d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans assert_not_implemented(len != 'l'); 552d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans s = va_arg(ap, char *); 553932d77dc8089af14d4d334188aa800d405fc51f6Chris Peterson slen = (prec < 0) ? strlen(s) : (size_t)prec; 554d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans APPEND_PADDED_S(s, slen, width, left_justify); 555d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans f++; 556d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 557d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans case 'p': { 558d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans uintmax_t val; 559d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans char buf[X2S_BUFSIZE]; 560d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 561cd9a1346e96f71bdecdc654ea50fc62d76371e74Jason Evans GET_ARG_NUMERIC(val, 'p'); 562d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans s = x2s(val, true, false, buf, &slen); 563d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans APPEND_PADDED_S(s, slen, width, left_justify); 564d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans f++; 565d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 5660c4e743eaf2ab6bcfd56e002fb82f95801b9292eJason Evans } default: not_reached(); 567d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } 568d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 569d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } default: { 570d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans APPEND_C(*f); 571d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans f++; 572d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans break; 573d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans }} 574d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } 575a1ee7838e14b321a97bfacb1f1cf5004198f2203Jason Evans label_out: 576d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans if (i < size) 577d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans str[i] = '\0'; 578d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans else 579d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans str[size - 1] = '\0'; 580d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans ret = i; 581d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 582d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#undef APPEND_C 583d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#undef APPEND_S 584d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#undef APPEND_PADDED_S 585d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans#undef GET_ARG_NUMERIC 586d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans return (ret); 587d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} 588d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 589d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason EvansJEMALLOC_ATTR(format(printf, 3, 4)) 590d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansint 591d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansmalloc_snprintf(char *str, size_t size, const char *format, ...) 592d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans{ 593d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans int ret; 594d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans va_list ap; 595d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 596d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans va_start(ap, format); 597d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans ret = malloc_vsnprintf(str, size, format, ap); 598d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans va_end(ap); 599d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 600d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans return (ret); 601d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} 602d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 603d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansvoid 604d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansmalloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque, 605d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans const char *format, va_list ap) 606d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans{ 607cd9a1346e96f71bdecdc654ea50fc62d76371e74Jason Evans char buf[MALLOC_PRINTF_BUFSIZE]; 608d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 609d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans if (write_cb == NULL) { 610d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans /* 611d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans * The caller did not provide an alternate write_cb callback 612d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans * function, so use the default one. malloc_write() is an 613d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans * inline function, so use malloc_message() directly here. 614d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans */ 6153597e91482c804592105ea078a0825fdb7c68dffMike Hommey write_cb = (je_malloc_message != NULL) ? je_malloc_message : 6163597e91482c804592105ea078a0825fdb7c68dffMike Hommey wrtmessage; 617d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans cbopaque = NULL; 618d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans } 619d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 620cd9a1346e96f71bdecdc654ea50fc62d76371e74Jason Evans malloc_vsnprintf(buf, sizeof(buf), format, ap); 621cd9a1346e96f71bdecdc654ea50fc62d76371e74Jason Evans write_cb(cbopaque, buf); 622d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} 623d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 624d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans/* 625d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans * Print to a callback function in such a way as to (hopefully) avoid memory 626d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans * allocation. 627d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans */ 628d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason EvansJEMALLOC_ATTR(format(printf, 3, 4)) 629d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansvoid 630d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansmalloc_cprintf(void (*write_cb)(void *, const char *), void *cbopaque, 631d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans const char *format, ...) 632d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans{ 633d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans va_list ap; 634d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 635d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans va_start(ap, format); 636d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans malloc_vcprintf(write_cb, cbopaque, format, ap); 637d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans va_end(ap); 638d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} 639d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 640d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans/* Print to stderr in such a way as to avoid memory allocation. */ 641d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason EvansJEMALLOC_ATTR(format(printf, 1, 2)) 642d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansvoid 643d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evansmalloc_printf(const char *format, ...) 644d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans{ 645d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans va_list ap; 646d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans 647d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans va_start(ap, format); 648d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans malloc_vcprintf(NULL, NULL, format, ap); 649d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans va_end(ap); 650d81e4bdd5c991bd5642c8b859ef1f752b51cd9beJason Evans} 651