10e9a2605SKonstantin Belousov /*- 20e9a2605SKonstantin Belousov * Copyright (c) 1986, 1988, 1991, 1993 30e9a2605SKonstantin Belousov * The Regents of the University of California. All rights reserved. 40e9a2605SKonstantin Belousov * (c) UNIX System Laboratories, Inc. 50e9a2605SKonstantin Belousov * All or some portions of this file are derived from material licensed 60e9a2605SKonstantin Belousov * to the University of California by American Telephone and Telegraph 70e9a2605SKonstantin Belousov * Co. or Unix System Laboratories, Inc. and are reproduced herein with 80e9a2605SKonstantin Belousov * the permission of UNIX System Laboratories, Inc. 90e9a2605SKonstantin Belousov * Copyright (c) 2011 Konstantin Belousov <kib@FreeBSD.org> 100e9a2605SKonstantin Belousov * 110e9a2605SKonstantin Belousov * Redistribution and use in source and binary forms, with or without 120e9a2605SKonstantin Belousov * modification, are permitted provided that the following conditions 130e9a2605SKonstantin Belousov * are met: 140e9a2605SKonstantin Belousov * 1. Redistributions of source code must retain the above copyright 150e9a2605SKonstantin Belousov * notice, this list of conditions and the following disclaimer. 160e9a2605SKonstantin Belousov * 2. Redistributions in binary form must reproduce the above copyright 170e9a2605SKonstantin Belousov * notice, this list of conditions and the following disclaimer in the 180e9a2605SKonstantin Belousov * documentation and/or other materials provided with the distribution. 19*fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 200e9a2605SKonstantin Belousov * may be used to endorse or promote products derived from this software 210e9a2605SKonstantin Belousov * without specific prior written permission. 220e9a2605SKonstantin Belousov * 230e9a2605SKonstantin Belousov * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 240e9a2605SKonstantin Belousov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 250e9a2605SKonstantin Belousov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 260e9a2605SKonstantin Belousov * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 270e9a2605SKonstantin Belousov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 280e9a2605SKonstantin Belousov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 290e9a2605SKonstantin Belousov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 300e9a2605SKonstantin Belousov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 310e9a2605SKonstantin Belousov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 320e9a2605SKonstantin Belousov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 330e9a2605SKonstantin Belousov * SUCH DAMAGE. 340e9a2605SKonstantin Belousov * 350e9a2605SKonstantin Belousov * $FreeBSD$ 360e9a2605SKonstantin Belousov */ 370e9a2605SKonstantin Belousov 380e9a2605SKonstantin Belousov #include <sys/param.h> 390e9a2605SKonstantin Belousov #include <inttypes.h> 400e9a2605SKonstantin Belousov #include <stdarg.h> 410e9a2605SKonstantin Belousov #include <stddef.h> 420e9a2605SKonstantin Belousov #include <string.h> 430e9a2605SKonstantin Belousov #include <unistd.h> 440e9a2605SKonstantin Belousov #include "rtld_printf.h" 450e9a2605SKonstantin Belousov 460e9a2605SKonstantin Belousov #define MAXNBUF (sizeof(intmax_t) * NBBY + 1) 470e9a2605SKonstantin Belousov 48b2367317SKonstantin Belousov #define PRINT_METHOD_SNPRINTF 1 49b2367317SKonstantin Belousov #define PRINT_METHOD_WRITE 2 50b2367317SKonstantin Belousov 510e9a2605SKonstantin Belousov struct snprintf_arg { 52b2367317SKonstantin Belousov int method; 530e9a2605SKonstantin Belousov char *str; 540e9a2605SKonstantin Belousov char *buf; 550e9a2605SKonstantin Belousov size_t remain; 560e9a2605SKonstantin Belousov size_t buf_total; 570e9a2605SKonstantin Belousov int fd; 580e9a2605SKonstantin Belousov }; 590e9a2605SKonstantin Belousov 600e9a2605SKonstantin Belousov static void 610e9a2605SKonstantin Belousov printf_out(struct snprintf_arg *info) 620e9a2605SKonstantin Belousov { 630e9a2605SKonstantin Belousov 640e9a2605SKonstantin Belousov if (info->remain == info->buf_total) 650e9a2605SKonstantin Belousov return; 660e9a2605SKonstantin Belousov write(info->fd, info->buf, info->buf_total - info->remain); 670e9a2605SKonstantin Belousov info->str = info->buf; 680e9a2605SKonstantin Belousov info->remain = info->buf_total; 690e9a2605SKonstantin Belousov } 700e9a2605SKonstantin Belousov 710e9a2605SKonstantin Belousov static void 72b2367317SKonstantin Belousov snprintf_func(int ch, struct snprintf_arg *const info) 730e9a2605SKonstantin Belousov { 740e9a2605SKonstantin Belousov 75b2367317SKonstantin Belousov switch (info->method) { 76b2367317SKonstantin Belousov case PRINT_METHOD_SNPRINTF: 77b2367317SKonstantin Belousov if (info->remain >= 2) { 78b2367317SKonstantin Belousov *info->str++ = ch; 79b2367317SKonstantin Belousov info->remain--; 80b2367317SKonstantin Belousov } 81b2367317SKonstantin Belousov break; 82b2367317SKonstantin Belousov case PRINT_METHOD_WRITE: 830e9a2605SKonstantin Belousov if (info->remain > 0) { 840e9a2605SKonstantin Belousov *info->str++ = ch; 850e9a2605SKonstantin Belousov info->remain--; 860e9a2605SKonstantin Belousov } else 870e9a2605SKonstantin Belousov printf_out(info); 88b2367317SKonstantin Belousov break; 89b2367317SKonstantin Belousov } 900e9a2605SKonstantin Belousov } 910e9a2605SKonstantin Belousov 925983b871SKonstantin Belousov static char const hex2ascii_lower[] = "0123456789abcdefghijklmnopqrstuvwxyz"; 935983b871SKonstantin Belousov static char const hex2ascii_upper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 945983b871SKonstantin Belousov #define hex2ascii(hex) (hex2ascii_lower[hex]) 955983b871SKonstantin Belousov #define hex2ascii_upper(hex) (hex2ascii_upper[hex]) 960e9a2605SKonstantin Belousov 970e9a2605SKonstantin Belousov static __inline int 980e9a2605SKonstantin Belousov imax(int a, int b) 990e9a2605SKonstantin Belousov { 1000e9a2605SKonstantin Belousov 1010e9a2605SKonstantin Belousov return (a > b ? a : b); 1020e9a2605SKonstantin Belousov } 1030e9a2605SKonstantin Belousov 1040e9a2605SKonstantin Belousov static char * 1050e9a2605SKonstantin Belousov ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) 1060e9a2605SKonstantin Belousov { 1070e9a2605SKonstantin Belousov char *p, c; 1080e9a2605SKonstantin Belousov 1090e9a2605SKonstantin Belousov p = nbuf; 1100e9a2605SKonstantin Belousov *p = '\0'; 1110e9a2605SKonstantin Belousov do { 1125983b871SKonstantin Belousov c = upper ? hex2ascii_upper(num % base) : 1135983b871SKonstantin Belousov hex2ascii(num % base); 1145983b871SKonstantin Belousov *++p = c; 1150e9a2605SKonstantin Belousov } while (num /= base); 1160e9a2605SKonstantin Belousov if (lenp) 1170e9a2605SKonstantin Belousov *lenp = p - nbuf; 1180e9a2605SKonstantin Belousov return (p); 1190e9a2605SKonstantin Belousov } 1200e9a2605SKonstantin Belousov 1210e9a2605SKonstantin Belousov static int 122b2367317SKonstantin Belousov kvprintf(char const *fmt, struct snprintf_arg *arg, int radix, va_list ap) 1230e9a2605SKonstantin Belousov { 124b2367317SKonstantin Belousov #define PCHAR(c) snprintf_func((c), arg) 1250e9a2605SKonstantin Belousov char nbuf[MAXNBUF]; 1260e9a2605SKonstantin Belousov const char *p, *percent, *q; 1270e9a2605SKonstantin Belousov u_char *up; 1280e9a2605SKonstantin Belousov int ch, n; 1290e9a2605SKonstantin Belousov uintmax_t num; 1300e9a2605SKonstantin Belousov int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; 1310e9a2605SKonstantin Belousov int cflag, hflag, jflag, tflag, zflag; 1320e9a2605SKonstantin Belousov int dwidth, upper; 1330e9a2605SKonstantin Belousov char padc; 1340e9a2605SKonstantin Belousov int stop = 0, retval = 0; 1350e9a2605SKonstantin Belousov 1360e9a2605SKonstantin Belousov num = 0; 1370e9a2605SKonstantin Belousov 1380e9a2605SKonstantin Belousov if (fmt == NULL) 1390e9a2605SKonstantin Belousov fmt = "(fmt null)\n"; 1400e9a2605SKonstantin Belousov 1410e9a2605SKonstantin Belousov if (radix < 2 || radix > 36) 1420e9a2605SKonstantin Belousov radix = 10; 1430e9a2605SKonstantin Belousov 1440e9a2605SKonstantin Belousov for (;;) { 1450e9a2605SKonstantin Belousov padc = ' '; 1460e9a2605SKonstantin Belousov width = 0; 1470e9a2605SKonstantin Belousov while ((ch = (u_char)*fmt++) != '%' || stop) { 1480e9a2605SKonstantin Belousov if (ch == '\0') 1490e9a2605SKonstantin Belousov return (retval); 1500e9a2605SKonstantin Belousov PCHAR(ch); 1510e9a2605SKonstantin Belousov } 1520e9a2605SKonstantin Belousov percent = fmt - 1; 1530e9a2605SKonstantin Belousov qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; 1540e9a2605SKonstantin Belousov sign = 0; dot = 0; dwidth = 0; upper = 0; 1550e9a2605SKonstantin Belousov cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0; 1560e9a2605SKonstantin Belousov reswitch: switch (ch = (u_char)*fmt++) { 1570e9a2605SKonstantin Belousov case '.': 1580e9a2605SKonstantin Belousov dot = 1; 1590e9a2605SKonstantin Belousov goto reswitch; 1600e9a2605SKonstantin Belousov case '#': 1610e9a2605SKonstantin Belousov sharpflag = 1; 1620e9a2605SKonstantin Belousov goto reswitch; 1630e9a2605SKonstantin Belousov case '+': 1640e9a2605SKonstantin Belousov sign = 1; 1650e9a2605SKonstantin Belousov goto reswitch; 1660e9a2605SKonstantin Belousov case '-': 1670e9a2605SKonstantin Belousov ladjust = 1; 1680e9a2605SKonstantin Belousov goto reswitch; 1690e9a2605SKonstantin Belousov case '%': 1700e9a2605SKonstantin Belousov PCHAR(ch); 1710e9a2605SKonstantin Belousov break; 1720e9a2605SKonstantin Belousov case '*': 1730e9a2605SKonstantin Belousov if (!dot) { 1740e9a2605SKonstantin Belousov width = va_arg(ap, int); 1750e9a2605SKonstantin Belousov if (width < 0) { 1760e9a2605SKonstantin Belousov ladjust = !ladjust; 1770e9a2605SKonstantin Belousov width = -width; 1780e9a2605SKonstantin Belousov } 1790e9a2605SKonstantin Belousov } else { 1800e9a2605SKonstantin Belousov dwidth = va_arg(ap, int); 1810e9a2605SKonstantin Belousov } 1820e9a2605SKonstantin Belousov goto reswitch; 1830e9a2605SKonstantin Belousov case '0': 1840e9a2605SKonstantin Belousov if (!dot) { 1850e9a2605SKonstantin Belousov padc = '0'; 1860e9a2605SKonstantin Belousov goto reswitch; 1870e9a2605SKonstantin Belousov } 1880e9a2605SKonstantin Belousov case '1': case '2': case '3': case '4': 1890e9a2605SKonstantin Belousov case '5': case '6': case '7': case '8': case '9': 1900e9a2605SKonstantin Belousov for (n = 0;; ++fmt) { 1910e9a2605SKonstantin Belousov n = n * 10 + ch - '0'; 1920e9a2605SKonstantin Belousov ch = *fmt; 1930e9a2605SKonstantin Belousov if (ch < '0' || ch > '9') 1940e9a2605SKonstantin Belousov break; 1950e9a2605SKonstantin Belousov } 1960e9a2605SKonstantin Belousov if (dot) 1970e9a2605SKonstantin Belousov dwidth = n; 1980e9a2605SKonstantin Belousov else 1990e9a2605SKonstantin Belousov width = n; 2000e9a2605SKonstantin Belousov goto reswitch; 2010e9a2605SKonstantin Belousov case 'b': 2020e9a2605SKonstantin Belousov num = (u_int)va_arg(ap, int); 2030e9a2605SKonstantin Belousov p = va_arg(ap, char *); 2040e9a2605SKonstantin Belousov for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;) 2050e9a2605SKonstantin Belousov PCHAR(*q--); 2060e9a2605SKonstantin Belousov 2070e9a2605SKonstantin Belousov if (num == 0) 2080e9a2605SKonstantin Belousov break; 2090e9a2605SKonstantin Belousov 2100e9a2605SKonstantin Belousov for (tmp = 0; *p;) { 2110e9a2605SKonstantin Belousov n = *p++; 2120e9a2605SKonstantin Belousov if (num & (1 << (n - 1))) { 2130e9a2605SKonstantin Belousov PCHAR(tmp ? ',' : '<'); 2140e9a2605SKonstantin Belousov for (; (n = *p) > ' '; ++p) 2150e9a2605SKonstantin Belousov PCHAR(n); 2160e9a2605SKonstantin Belousov tmp = 1; 2170e9a2605SKonstantin Belousov } else 2180e9a2605SKonstantin Belousov for (; *p > ' '; ++p) 2190e9a2605SKonstantin Belousov continue; 2200e9a2605SKonstantin Belousov } 2210e9a2605SKonstantin Belousov if (tmp) 2220e9a2605SKonstantin Belousov PCHAR('>'); 2230e9a2605SKonstantin Belousov break; 2240e9a2605SKonstantin Belousov case 'c': 2250e9a2605SKonstantin Belousov PCHAR(va_arg(ap, int)); 2260e9a2605SKonstantin Belousov break; 2270e9a2605SKonstantin Belousov case 'D': 2280e9a2605SKonstantin Belousov up = va_arg(ap, u_char *); 2290e9a2605SKonstantin Belousov p = va_arg(ap, char *); 2300e9a2605SKonstantin Belousov if (!width) 2310e9a2605SKonstantin Belousov width = 16; 2320e9a2605SKonstantin Belousov while(width--) { 2330e9a2605SKonstantin Belousov PCHAR(hex2ascii(*up >> 4)); 2340e9a2605SKonstantin Belousov PCHAR(hex2ascii(*up & 0x0f)); 2350e9a2605SKonstantin Belousov up++; 2360e9a2605SKonstantin Belousov if (width) 2370e9a2605SKonstantin Belousov for (q=p;*q;q++) 2380e9a2605SKonstantin Belousov PCHAR(*q); 2390e9a2605SKonstantin Belousov } 2400e9a2605SKonstantin Belousov break; 2410e9a2605SKonstantin Belousov case 'd': 2420e9a2605SKonstantin Belousov case 'i': 2430e9a2605SKonstantin Belousov base = 10; 2440e9a2605SKonstantin Belousov sign = 1; 2450e9a2605SKonstantin Belousov goto handle_sign; 2460e9a2605SKonstantin Belousov case 'h': 2470e9a2605SKonstantin Belousov if (hflag) { 2480e9a2605SKonstantin Belousov hflag = 0; 2490e9a2605SKonstantin Belousov cflag = 1; 2500e9a2605SKonstantin Belousov } else 2510e9a2605SKonstantin Belousov hflag = 1; 2520e9a2605SKonstantin Belousov goto reswitch; 2530e9a2605SKonstantin Belousov case 'j': 2540e9a2605SKonstantin Belousov jflag = 1; 2550e9a2605SKonstantin Belousov goto reswitch; 2560e9a2605SKonstantin Belousov case 'l': 2570e9a2605SKonstantin Belousov if (lflag) { 2580e9a2605SKonstantin Belousov lflag = 0; 2590e9a2605SKonstantin Belousov qflag = 1; 2600e9a2605SKonstantin Belousov } else 2610e9a2605SKonstantin Belousov lflag = 1; 2620e9a2605SKonstantin Belousov goto reswitch; 2630e9a2605SKonstantin Belousov case 'n': 2640e9a2605SKonstantin Belousov if (jflag) 2650e9a2605SKonstantin Belousov *(va_arg(ap, intmax_t *)) = retval; 2660e9a2605SKonstantin Belousov else if (qflag) 2670e9a2605SKonstantin Belousov *(va_arg(ap, quad_t *)) = retval; 2680e9a2605SKonstantin Belousov else if (lflag) 2690e9a2605SKonstantin Belousov *(va_arg(ap, long *)) = retval; 2700e9a2605SKonstantin Belousov else if (zflag) 2710e9a2605SKonstantin Belousov *(va_arg(ap, size_t *)) = retval; 2720e9a2605SKonstantin Belousov else if (hflag) 2730e9a2605SKonstantin Belousov *(va_arg(ap, short *)) = retval; 2740e9a2605SKonstantin Belousov else if (cflag) 2750e9a2605SKonstantin Belousov *(va_arg(ap, char *)) = retval; 2760e9a2605SKonstantin Belousov else 2770e9a2605SKonstantin Belousov *(va_arg(ap, int *)) = retval; 2780e9a2605SKonstantin Belousov break; 2790e9a2605SKonstantin Belousov case 'o': 2800e9a2605SKonstantin Belousov base = 8; 2810e9a2605SKonstantin Belousov goto handle_nosign; 2820e9a2605SKonstantin Belousov case 'p': 2830e9a2605SKonstantin Belousov base = 16; 2840e9a2605SKonstantin Belousov sharpflag = (width == 0); 2850e9a2605SKonstantin Belousov sign = 0; 2860e9a2605SKonstantin Belousov num = (uintptr_t)va_arg(ap, void *); 2870e9a2605SKonstantin Belousov goto number; 2880e9a2605SKonstantin Belousov case 'q': 2890e9a2605SKonstantin Belousov qflag = 1; 2900e9a2605SKonstantin Belousov goto reswitch; 2910e9a2605SKonstantin Belousov case 'r': 2920e9a2605SKonstantin Belousov base = radix; 2930e9a2605SKonstantin Belousov if (sign) 2940e9a2605SKonstantin Belousov goto handle_sign; 2950e9a2605SKonstantin Belousov goto handle_nosign; 2960e9a2605SKonstantin Belousov case 's': 2970e9a2605SKonstantin Belousov p = va_arg(ap, char *); 2980e9a2605SKonstantin Belousov if (p == NULL) 2990e9a2605SKonstantin Belousov p = "(null)"; 3000e9a2605SKonstantin Belousov if (!dot) 3010e9a2605SKonstantin Belousov n = strlen (p); 3020e9a2605SKonstantin Belousov else 3030e9a2605SKonstantin Belousov for (n = 0; n < dwidth && p[n]; n++) 3040e9a2605SKonstantin Belousov continue; 3050e9a2605SKonstantin Belousov 3060e9a2605SKonstantin Belousov width -= n; 3070e9a2605SKonstantin Belousov 3080e9a2605SKonstantin Belousov if (!ladjust && width > 0) 3090e9a2605SKonstantin Belousov while (width--) 3100e9a2605SKonstantin Belousov PCHAR(padc); 3110e9a2605SKonstantin Belousov while (n--) 3120e9a2605SKonstantin Belousov PCHAR(*p++); 3130e9a2605SKonstantin Belousov if (ladjust && width > 0) 3140e9a2605SKonstantin Belousov while (width--) 3150e9a2605SKonstantin Belousov PCHAR(padc); 3160e9a2605SKonstantin Belousov break; 3170e9a2605SKonstantin Belousov case 't': 3180e9a2605SKonstantin Belousov tflag = 1; 3190e9a2605SKonstantin Belousov goto reswitch; 3200e9a2605SKonstantin Belousov case 'u': 3210e9a2605SKonstantin Belousov base = 10; 3220e9a2605SKonstantin Belousov goto handle_nosign; 3230e9a2605SKonstantin Belousov case 'X': 3240e9a2605SKonstantin Belousov upper = 1; 3250e9a2605SKonstantin Belousov case 'x': 3260e9a2605SKonstantin Belousov base = 16; 3270e9a2605SKonstantin Belousov goto handle_nosign; 3280e9a2605SKonstantin Belousov case 'y': 3290e9a2605SKonstantin Belousov base = 16; 3300e9a2605SKonstantin Belousov sign = 1; 3310e9a2605SKonstantin Belousov goto handle_sign; 3320e9a2605SKonstantin Belousov case 'z': 3330e9a2605SKonstantin Belousov zflag = 1; 3340e9a2605SKonstantin Belousov goto reswitch; 3350e9a2605SKonstantin Belousov handle_nosign: 3360e9a2605SKonstantin Belousov sign = 0; 3370e9a2605SKonstantin Belousov if (jflag) 3380e9a2605SKonstantin Belousov num = va_arg(ap, uintmax_t); 3390e9a2605SKonstantin Belousov else if (qflag) 3400e9a2605SKonstantin Belousov num = va_arg(ap, u_quad_t); 3410e9a2605SKonstantin Belousov else if (tflag) 3420e9a2605SKonstantin Belousov num = va_arg(ap, ptrdiff_t); 3430e9a2605SKonstantin Belousov else if (lflag) 3440e9a2605SKonstantin Belousov num = va_arg(ap, u_long); 3450e9a2605SKonstantin Belousov else if (zflag) 3460e9a2605SKonstantin Belousov num = va_arg(ap, size_t); 3470e9a2605SKonstantin Belousov else if (hflag) 3480e9a2605SKonstantin Belousov num = (u_short)va_arg(ap, int); 3490e9a2605SKonstantin Belousov else if (cflag) 3500e9a2605SKonstantin Belousov num = (u_char)va_arg(ap, int); 3510e9a2605SKonstantin Belousov else 3520e9a2605SKonstantin Belousov num = va_arg(ap, u_int); 3530e9a2605SKonstantin Belousov goto number; 3540e9a2605SKonstantin Belousov handle_sign: 3550e9a2605SKonstantin Belousov if (jflag) 3560e9a2605SKonstantin Belousov num = va_arg(ap, intmax_t); 3570e9a2605SKonstantin Belousov else if (qflag) 3580e9a2605SKonstantin Belousov num = va_arg(ap, quad_t); 3590e9a2605SKonstantin Belousov else if (tflag) 3600e9a2605SKonstantin Belousov num = va_arg(ap, ptrdiff_t); 3610e9a2605SKonstantin Belousov else if (lflag) 3620e9a2605SKonstantin Belousov num = va_arg(ap, long); 3630e9a2605SKonstantin Belousov else if (zflag) 3640e9a2605SKonstantin Belousov num = va_arg(ap, ssize_t); 3650e9a2605SKonstantin Belousov else if (hflag) 3660e9a2605SKonstantin Belousov num = (short)va_arg(ap, int); 3670e9a2605SKonstantin Belousov else if (cflag) 3680e9a2605SKonstantin Belousov num = (char)va_arg(ap, int); 3690e9a2605SKonstantin Belousov else 3700e9a2605SKonstantin Belousov num = va_arg(ap, int); 3710e9a2605SKonstantin Belousov number: 3720e9a2605SKonstantin Belousov if (sign && (intmax_t)num < 0) { 3730e9a2605SKonstantin Belousov neg = 1; 3740e9a2605SKonstantin Belousov num = -(intmax_t)num; 3750e9a2605SKonstantin Belousov } 3760e9a2605SKonstantin Belousov p = ksprintn(nbuf, num, base, &n, upper); 3770e9a2605SKonstantin Belousov tmp = 0; 3780e9a2605SKonstantin Belousov if (sharpflag && num != 0) { 3790e9a2605SKonstantin Belousov if (base == 8) 3800e9a2605SKonstantin Belousov tmp++; 3810e9a2605SKonstantin Belousov else if (base == 16) 3820e9a2605SKonstantin Belousov tmp += 2; 3830e9a2605SKonstantin Belousov } 3840e9a2605SKonstantin Belousov if (neg) 3850e9a2605SKonstantin Belousov tmp++; 3860e9a2605SKonstantin Belousov 3870e9a2605SKonstantin Belousov if (!ladjust && padc == '0') 3880e9a2605SKonstantin Belousov dwidth = width - tmp; 3890e9a2605SKonstantin Belousov width -= tmp + imax(dwidth, n); 3900e9a2605SKonstantin Belousov dwidth -= n; 3910e9a2605SKonstantin Belousov if (!ladjust) 3920e9a2605SKonstantin Belousov while (width-- > 0) 3930e9a2605SKonstantin Belousov PCHAR(' '); 3940e9a2605SKonstantin Belousov if (neg) 3950e9a2605SKonstantin Belousov PCHAR('-'); 3960e9a2605SKonstantin Belousov if (sharpflag && num != 0) { 3970e9a2605SKonstantin Belousov if (base == 8) { 3980e9a2605SKonstantin Belousov PCHAR('0'); 3990e9a2605SKonstantin Belousov } else if (base == 16) { 4000e9a2605SKonstantin Belousov PCHAR('0'); 4010e9a2605SKonstantin Belousov PCHAR('x'); 4020e9a2605SKonstantin Belousov } 4030e9a2605SKonstantin Belousov } 4040e9a2605SKonstantin Belousov while (dwidth-- > 0) 4050e9a2605SKonstantin Belousov PCHAR('0'); 4060e9a2605SKonstantin Belousov 4070e9a2605SKonstantin Belousov while (*p) 4080e9a2605SKonstantin Belousov PCHAR(*p--); 4090e9a2605SKonstantin Belousov 4100e9a2605SKonstantin Belousov if (ladjust) 4110e9a2605SKonstantin Belousov while (width-- > 0) 4120e9a2605SKonstantin Belousov PCHAR(' '); 4130e9a2605SKonstantin Belousov 4140e9a2605SKonstantin Belousov break; 4150e9a2605SKonstantin Belousov default: 4160e9a2605SKonstantin Belousov while (percent < fmt) 4170e9a2605SKonstantin Belousov PCHAR(*percent++); 4180e9a2605SKonstantin Belousov /* 4190e9a2605SKonstantin Belousov * Since we ignore an formatting argument it is no 4200e9a2605SKonstantin Belousov * longer safe to obey the remaining formatting 4210e9a2605SKonstantin Belousov * arguments as the arguments will no longer match 4220e9a2605SKonstantin Belousov * the format specs. 4230e9a2605SKonstantin Belousov */ 4240e9a2605SKonstantin Belousov stop = 1; 4250e9a2605SKonstantin Belousov break; 4260e9a2605SKonstantin Belousov } 4270e9a2605SKonstantin Belousov } 4280e9a2605SKonstantin Belousov #undef PCHAR 4290e9a2605SKonstantin Belousov } 4300e9a2605SKonstantin Belousov 4310e9a2605SKonstantin Belousov int 43202d3b38eSJonathan Anderson rtld_snprintf(char *buf, size_t bufsize, const char *fmt, ...) 43302d3b38eSJonathan Anderson { 43402d3b38eSJonathan Anderson va_list ap; 43502d3b38eSJonathan Anderson int retval; 43602d3b38eSJonathan Anderson 43702d3b38eSJonathan Anderson va_start(ap, fmt); 43802d3b38eSJonathan Anderson retval = rtld_vsnprintf(buf, bufsize, fmt, ap); 43902d3b38eSJonathan Anderson va_end(ap); 44002d3b38eSJonathan Anderson return (retval); 44102d3b38eSJonathan Anderson } 44202d3b38eSJonathan Anderson 44302d3b38eSJonathan Anderson int 4440e9a2605SKonstantin Belousov rtld_vsnprintf(char *buf, size_t bufsize, const char *fmt, va_list ap) 4450e9a2605SKonstantin Belousov { 4460e9a2605SKonstantin Belousov struct snprintf_arg info; 4470e9a2605SKonstantin Belousov int retval; 4480e9a2605SKonstantin Belousov 449b2367317SKonstantin Belousov info.method = PRINT_METHOD_SNPRINTF; 4500e9a2605SKonstantin Belousov info.buf = info.str = buf; 4510e9a2605SKonstantin Belousov info.buf_total = info.remain = bufsize; 4520e9a2605SKonstantin Belousov info.fd = -1; 453b2367317SKonstantin Belousov retval = kvprintf(fmt, &info, 10, ap); 4540e9a2605SKonstantin Belousov if (info.remain >= 1) 4550e9a2605SKonstantin Belousov *info.str++ = '\0'; 4560e9a2605SKonstantin Belousov return (retval); 4570e9a2605SKonstantin Belousov } 4580e9a2605SKonstantin Belousov 4590e9a2605SKonstantin Belousov int 4600e9a2605SKonstantin Belousov rtld_vfdprintf(int fd, const char *fmt, va_list ap) 4610e9a2605SKonstantin Belousov { 4620e9a2605SKonstantin Belousov char buf[512]; 4630e9a2605SKonstantin Belousov struct snprintf_arg info; 4640e9a2605SKonstantin Belousov int retval; 4650e9a2605SKonstantin Belousov 466b2367317SKonstantin Belousov info.method = PRINT_METHOD_WRITE; 4670e9a2605SKonstantin Belousov info.buf = info.str = buf; 4680e9a2605SKonstantin Belousov info.buf_total = info.remain = sizeof(buf); 4690e9a2605SKonstantin Belousov info.fd = fd; 470b2367317SKonstantin Belousov retval = kvprintf(fmt, &info, 10, ap); 4710e9a2605SKonstantin Belousov printf_out(&info); 4720e9a2605SKonstantin Belousov return (retval); 4730e9a2605SKonstantin Belousov } 4740e9a2605SKonstantin Belousov 4750e9a2605SKonstantin Belousov int 4760e9a2605SKonstantin Belousov rtld_fdprintf(int fd, const char *fmt, ...) 4770e9a2605SKonstantin Belousov { 4780e9a2605SKonstantin Belousov va_list ap; 4790e9a2605SKonstantin Belousov int retval; 4800e9a2605SKonstantin Belousov 4810e9a2605SKonstantin Belousov va_start(ap, fmt); 4820e9a2605SKonstantin Belousov retval = rtld_vfdprintf(fd, fmt, ap); 4830e9a2605SKonstantin Belousov va_end(ap); 4840e9a2605SKonstantin Belousov return (retval); 4850e9a2605SKonstantin Belousov } 4860e9a2605SKonstantin Belousov 4870e9a2605SKonstantin Belousov void 4880e9a2605SKonstantin Belousov rtld_fdputstr(int fd, const char *str) 4890e9a2605SKonstantin Belousov { 4900e9a2605SKonstantin Belousov 4910e9a2605SKonstantin Belousov write(fd, str, strlen(str)); 4920e9a2605SKonstantin Belousov } 4930e9a2605SKonstantin Belousov 4940e9a2605SKonstantin Belousov void 4950e9a2605SKonstantin Belousov rtld_fdputchar(int fd, int c) 4960e9a2605SKonstantin Belousov { 4970e9a2605SKonstantin Belousov char c1; 4980e9a2605SKonstantin Belousov 4990e9a2605SKonstantin Belousov c1 = c; 5000e9a2605SKonstantin Belousov write(fd, &c1, 1); 5010e9a2605SKonstantin Belousov } 502