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. 190e9a2605SKonstantin Belousov * 4. 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 <ctype.h> 400e9a2605SKonstantin Belousov #include <inttypes.h> 410e9a2605SKonstantin Belousov #include <stdarg.h> 420e9a2605SKonstantin Belousov #include <stddef.h> 430e9a2605SKonstantin Belousov #include <string.h> 440e9a2605SKonstantin Belousov #include <unistd.h> 450e9a2605SKonstantin Belousov #include "rtld_printf.h" 460e9a2605SKonstantin Belousov 470e9a2605SKonstantin Belousov #define MAXNBUF (sizeof(intmax_t) * NBBY + 1) 480e9a2605SKonstantin Belousov 49*b2367317SKonstantin Belousov #define PRINT_METHOD_SNPRINTF 1 50*b2367317SKonstantin Belousov #define PRINT_METHOD_WRITE 2 51*b2367317SKonstantin Belousov 520e9a2605SKonstantin Belousov struct snprintf_arg { 53*b2367317SKonstantin Belousov int method; 540e9a2605SKonstantin Belousov char *str; 550e9a2605SKonstantin Belousov char *buf; 560e9a2605SKonstantin Belousov size_t remain; 570e9a2605SKonstantin Belousov size_t buf_total; 580e9a2605SKonstantin Belousov int fd; 590e9a2605SKonstantin Belousov }; 600e9a2605SKonstantin Belousov 610e9a2605SKonstantin Belousov static void 620e9a2605SKonstantin Belousov printf_out(struct snprintf_arg *info) 630e9a2605SKonstantin Belousov { 640e9a2605SKonstantin Belousov 650e9a2605SKonstantin Belousov if (info->remain == info->buf_total) 660e9a2605SKonstantin Belousov return; 670e9a2605SKonstantin Belousov write(info->fd, info->buf, info->buf_total - info->remain); 680e9a2605SKonstantin Belousov info->str = info->buf; 690e9a2605SKonstantin Belousov info->remain = info->buf_total; 700e9a2605SKonstantin Belousov } 710e9a2605SKonstantin Belousov 720e9a2605SKonstantin Belousov static void 73*b2367317SKonstantin Belousov snprintf_func(int ch, struct snprintf_arg *const info) 740e9a2605SKonstantin Belousov { 750e9a2605SKonstantin Belousov 76*b2367317SKonstantin Belousov switch (info->method) { 77*b2367317SKonstantin Belousov case PRINT_METHOD_SNPRINTF: 78*b2367317SKonstantin Belousov if (info->remain >= 2) { 79*b2367317SKonstantin Belousov *info->str++ = ch; 80*b2367317SKonstantin Belousov info->remain--; 81*b2367317SKonstantin Belousov } 82*b2367317SKonstantin Belousov break; 83*b2367317SKonstantin Belousov case PRINT_METHOD_WRITE: 840e9a2605SKonstantin Belousov if (info->remain > 0) { 850e9a2605SKonstantin Belousov *info->str++ = ch; 860e9a2605SKonstantin Belousov info->remain--; 870e9a2605SKonstantin Belousov } else 880e9a2605SKonstantin Belousov printf_out(info); 89*b2367317SKonstantin Belousov break; 90*b2367317SKonstantin Belousov } 910e9a2605SKonstantin Belousov } 920e9a2605SKonstantin Belousov 930e9a2605SKonstantin Belousov static char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz"; 940e9a2605SKonstantin Belousov #define hex2ascii(hex) (hex2ascii_data[hex]) 950e9a2605SKonstantin Belousov 960e9a2605SKonstantin Belousov static __inline int 970e9a2605SKonstantin Belousov imax(int a, int b) 980e9a2605SKonstantin Belousov { 990e9a2605SKonstantin Belousov 1000e9a2605SKonstantin Belousov return (a > b ? a : b); 1010e9a2605SKonstantin Belousov } 1020e9a2605SKonstantin Belousov 1030e9a2605SKonstantin Belousov static char * 1040e9a2605SKonstantin Belousov ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) 1050e9a2605SKonstantin Belousov { 1060e9a2605SKonstantin Belousov char *p, c; 1070e9a2605SKonstantin Belousov 1080e9a2605SKonstantin Belousov p = nbuf; 1090e9a2605SKonstantin Belousov *p = '\0'; 1100e9a2605SKonstantin Belousov do { 1110e9a2605SKonstantin Belousov c = hex2ascii(num % base); 1120e9a2605SKonstantin Belousov *++p = upper ? toupper(c) : c; 1130e9a2605SKonstantin Belousov } while (num /= base); 1140e9a2605SKonstantin Belousov if (lenp) 1150e9a2605SKonstantin Belousov *lenp = p - nbuf; 1160e9a2605SKonstantin Belousov return (p); 1170e9a2605SKonstantin Belousov } 1180e9a2605SKonstantin Belousov 1190e9a2605SKonstantin Belousov static int 120*b2367317SKonstantin Belousov kvprintf(char const *fmt, struct snprintf_arg *arg, int radix, va_list ap) 1210e9a2605SKonstantin Belousov { 122*b2367317SKonstantin Belousov #define PCHAR(c) snprintf_func((c), arg) 1230e9a2605SKonstantin Belousov char nbuf[MAXNBUF]; 1240e9a2605SKonstantin Belousov const char *p, *percent, *q; 1250e9a2605SKonstantin Belousov u_char *up; 1260e9a2605SKonstantin Belousov int ch, n; 1270e9a2605SKonstantin Belousov uintmax_t num; 1280e9a2605SKonstantin Belousov int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; 1290e9a2605SKonstantin Belousov int cflag, hflag, jflag, tflag, zflag; 1300e9a2605SKonstantin Belousov int dwidth, upper; 1310e9a2605SKonstantin Belousov char padc; 1320e9a2605SKonstantin Belousov int stop = 0, retval = 0; 1330e9a2605SKonstantin Belousov 1340e9a2605SKonstantin Belousov num = 0; 1350e9a2605SKonstantin Belousov 1360e9a2605SKonstantin Belousov if (fmt == NULL) 1370e9a2605SKonstantin Belousov fmt = "(fmt null)\n"; 1380e9a2605SKonstantin Belousov 1390e9a2605SKonstantin Belousov if (radix < 2 || radix > 36) 1400e9a2605SKonstantin Belousov radix = 10; 1410e9a2605SKonstantin Belousov 1420e9a2605SKonstantin Belousov for (;;) { 1430e9a2605SKonstantin Belousov padc = ' '; 1440e9a2605SKonstantin Belousov width = 0; 1450e9a2605SKonstantin Belousov while ((ch = (u_char)*fmt++) != '%' || stop) { 1460e9a2605SKonstantin Belousov if (ch == '\0') 1470e9a2605SKonstantin Belousov return (retval); 1480e9a2605SKonstantin Belousov PCHAR(ch); 1490e9a2605SKonstantin Belousov } 1500e9a2605SKonstantin Belousov percent = fmt - 1; 1510e9a2605SKonstantin Belousov qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; 1520e9a2605SKonstantin Belousov sign = 0; dot = 0; dwidth = 0; upper = 0; 1530e9a2605SKonstantin Belousov cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0; 1540e9a2605SKonstantin Belousov reswitch: switch (ch = (u_char)*fmt++) { 1550e9a2605SKonstantin Belousov case '.': 1560e9a2605SKonstantin Belousov dot = 1; 1570e9a2605SKonstantin Belousov goto reswitch; 1580e9a2605SKonstantin Belousov case '#': 1590e9a2605SKonstantin Belousov sharpflag = 1; 1600e9a2605SKonstantin Belousov goto reswitch; 1610e9a2605SKonstantin Belousov case '+': 1620e9a2605SKonstantin Belousov sign = 1; 1630e9a2605SKonstantin Belousov goto reswitch; 1640e9a2605SKonstantin Belousov case '-': 1650e9a2605SKonstantin Belousov ladjust = 1; 1660e9a2605SKonstantin Belousov goto reswitch; 1670e9a2605SKonstantin Belousov case '%': 1680e9a2605SKonstantin Belousov PCHAR(ch); 1690e9a2605SKonstantin Belousov break; 1700e9a2605SKonstantin Belousov case '*': 1710e9a2605SKonstantin Belousov if (!dot) { 1720e9a2605SKonstantin Belousov width = va_arg(ap, int); 1730e9a2605SKonstantin Belousov if (width < 0) { 1740e9a2605SKonstantin Belousov ladjust = !ladjust; 1750e9a2605SKonstantin Belousov width = -width; 1760e9a2605SKonstantin Belousov } 1770e9a2605SKonstantin Belousov } else { 1780e9a2605SKonstantin Belousov dwidth = va_arg(ap, int); 1790e9a2605SKonstantin Belousov } 1800e9a2605SKonstantin Belousov goto reswitch; 1810e9a2605SKonstantin Belousov case '0': 1820e9a2605SKonstantin Belousov if (!dot) { 1830e9a2605SKonstantin Belousov padc = '0'; 1840e9a2605SKonstantin Belousov goto reswitch; 1850e9a2605SKonstantin Belousov } 1860e9a2605SKonstantin Belousov case '1': case '2': case '3': case '4': 1870e9a2605SKonstantin Belousov case '5': case '6': case '7': case '8': case '9': 1880e9a2605SKonstantin Belousov for (n = 0;; ++fmt) { 1890e9a2605SKonstantin Belousov n = n * 10 + ch - '0'; 1900e9a2605SKonstantin Belousov ch = *fmt; 1910e9a2605SKonstantin Belousov if (ch < '0' || ch > '9') 1920e9a2605SKonstantin Belousov break; 1930e9a2605SKonstantin Belousov } 1940e9a2605SKonstantin Belousov if (dot) 1950e9a2605SKonstantin Belousov dwidth = n; 1960e9a2605SKonstantin Belousov else 1970e9a2605SKonstantin Belousov width = n; 1980e9a2605SKonstantin Belousov goto reswitch; 1990e9a2605SKonstantin Belousov case 'b': 2000e9a2605SKonstantin Belousov num = (u_int)va_arg(ap, int); 2010e9a2605SKonstantin Belousov p = va_arg(ap, char *); 2020e9a2605SKonstantin Belousov for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;) 2030e9a2605SKonstantin Belousov PCHAR(*q--); 2040e9a2605SKonstantin Belousov 2050e9a2605SKonstantin Belousov if (num == 0) 2060e9a2605SKonstantin Belousov break; 2070e9a2605SKonstantin Belousov 2080e9a2605SKonstantin Belousov for (tmp = 0; *p;) { 2090e9a2605SKonstantin Belousov n = *p++; 2100e9a2605SKonstantin Belousov if (num & (1 << (n - 1))) { 2110e9a2605SKonstantin Belousov PCHAR(tmp ? ',' : '<'); 2120e9a2605SKonstantin Belousov for (; (n = *p) > ' '; ++p) 2130e9a2605SKonstantin Belousov PCHAR(n); 2140e9a2605SKonstantin Belousov tmp = 1; 2150e9a2605SKonstantin Belousov } else 2160e9a2605SKonstantin Belousov for (; *p > ' '; ++p) 2170e9a2605SKonstantin Belousov continue; 2180e9a2605SKonstantin Belousov } 2190e9a2605SKonstantin Belousov if (tmp) 2200e9a2605SKonstantin Belousov PCHAR('>'); 2210e9a2605SKonstantin Belousov break; 2220e9a2605SKonstantin Belousov case 'c': 2230e9a2605SKonstantin Belousov PCHAR(va_arg(ap, int)); 2240e9a2605SKonstantin Belousov break; 2250e9a2605SKonstantin Belousov case 'D': 2260e9a2605SKonstantin Belousov up = va_arg(ap, u_char *); 2270e9a2605SKonstantin Belousov p = va_arg(ap, char *); 2280e9a2605SKonstantin Belousov if (!width) 2290e9a2605SKonstantin Belousov width = 16; 2300e9a2605SKonstantin Belousov while(width--) { 2310e9a2605SKonstantin Belousov PCHAR(hex2ascii(*up >> 4)); 2320e9a2605SKonstantin Belousov PCHAR(hex2ascii(*up & 0x0f)); 2330e9a2605SKonstantin Belousov up++; 2340e9a2605SKonstantin Belousov if (width) 2350e9a2605SKonstantin Belousov for (q=p;*q;q++) 2360e9a2605SKonstantin Belousov PCHAR(*q); 2370e9a2605SKonstantin Belousov } 2380e9a2605SKonstantin Belousov break; 2390e9a2605SKonstantin Belousov case 'd': 2400e9a2605SKonstantin Belousov case 'i': 2410e9a2605SKonstantin Belousov base = 10; 2420e9a2605SKonstantin Belousov sign = 1; 2430e9a2605SKonstantin Belousov goto handle_sign; 2440e9a2605SKonstantin Belousov case 'h': 2450e9a2605SKonstantin Belousov if (hflag) { 2460e9a2605SKonstantin Belousov hflag = 0; 2470e9a2605SKonstantin Belousov cflag = 1; 2480e9a2605SKonstantin Belousov } else 2490e9a2605SKonstantin Belousov hflag = 1; 2500e9a2605SKonstantin Belousov goto reswitch; 2510e9a2605SKonstantin Belousov case 'j': 2520e9a2605SKonstantin Belousov jflag = 1; 2530e9a2605SKonstantin Belousov goto reswitch; 2540e9a2605SKonstantin Belousov case 'l': 2550e9a2605SKonstantin Belousov if (lflag) { 2560e9a2605SKonstantin Belousov lflag = 0; 2570e9a2605SKonstantin Belousov qflag = 1; 2580e9a2605SKonstantin Belousov } else 2590e9a2605SKonstantin Belousov lflag = 1; 2600e9a2605SKonstantin Belousov goto reswitch; 2610e9a2605SKonstantin Belousov case 'n': 2620e9a2605SKonstantin Belousov if (jflag) 2630e9a2605SKonstantin Belousov *(va_arg(ap, intmax_t *)) = retval; 2640e9a2605SKonstantin Belousov else if (qflag) 2650e9a2605SKonstantin Belousov *(va_arg(ap, quad_t *)) = retval; 2660e9a2605SKonstantin Belousov else if (lflag) 2670e9a2605SKonstantin Belousov *(va_arg(ap, long *)) = retval; 2680e9a2605SKonstantin Belousov else if (zflag) 2690e9a2605SKonstantin Belousov *(va_arg(ap, size_t *)) = retval; 2700e9a2605SKonstantin Belousov else if (hflag) 2710e9a2605SKonstantin Belousov *(va_arg(ap, short *)) = retval; 2720e9a2605SKonstantin Belousov else if (cflag) 2730e9a2605SKonstantin Belousov *(va_arg(ap, char *)) = retval; 2740e9a2605SKonstantin Belousov else 2750e9a2605SKonstantin Belousov *(va_arg(ap, int *)) = retval; 2760e9a2605SKonstantin Belousov break; 2770e9a2605SKonstantin Belousov case 'o': 2780e9a2605SKonstantin Belousov base = 8; 2790e9a2605SKonstantin Belousov goto handle_nosign; 2800e9a2605SKonstantin Belousov case 'p': 2810e9a2605SKonstantin Belousov base = 16; 2820e9a2605SKonstantin Belousov sharpflag = (width == 0); 2830e9a2605SKonstantin Belousov sign = 0; 2840e9a2605SKonstantin Belousov num = (uintptr_t)va_arg(ap, void *); 2850e9a2605SKonstantin Belousov goto number; 2860e9a2605SKonstantin Belousov case 'q': 2870e9a2605SKonstantin Belousov qflag = 1; 2880e9a2605SKonstantin Belousov goto reswitch; 2890e9a2605SKonstantin Belousov case 'r': 2900e9a2605SKonstantin Belousov base = radix; 2910e9a2605SKonstantin Belousov if (sign) 2920e9a2605SKonstantin Belousov goto handle_sign; 2930e9a2605SKonstantin Belousov goto handle_nosign; 2940e9a2605SKonstantin Belousov case 's': 2950e9a2605SKonstantin Belousov p = va_arg(ap, char *); 2960e9a2605SKonstantin Belousov if (p == NULL) 2970e9a2605SKonstantin Belousov p = "(null)"; 2980e9a2605SKonstantin Belousov if (!dot) 2990e9a2605SKonstantin Belousov n = strlen (p); 3000e9a2605SKonstantin Belousov else 3010e9a2605SKonstantin Belousov for (n = 0; n < dwidth && p[n]; n++) 3020e9a2605SKonstantin Belousov continue; 3030e9a2605SKonstantin Belousov 3040e9a2605SKonstantin Belousov width -= n; 3050e9a2605SKonstantin Belousov 3060e9a2605SKonstantin Belousov if (!ladjust && width > 0) 3070e9a2605SKonstantin Belousov while (width--) 3080e9a2605SKonstantin Belousov PCHAR(padc); 3090e9a2605SKonstantin Belousov while (n--) 3100e9a2605SKonstantin Belousov PCHAR(*p++); 3110e9a2605SKonstantin Belousov if (ladjust && width > 0) 3120e9a2605SKonstantin Belousov while (width--) 3130e9a2605SKonstantin Belousov PCHAR(padc); 3140e9a2605SKonstantin Belousov break; 3150e9a2605SKonstantin Belousov case 't': 3160e9a2605SKonstantin Belousov tflag = 1; 3170e9a2605SKonstantin Belousov goto reswitch; 3180e9a2605SKonstantin Belousov case 'u': 3190e9a2605SKonstantin Belousov base = 10; 3200e9a2605SKonstantin Belousov goto handle_nosign; 3210e9a2605SKonstantin Belousov case 'X': 3220e9a2605SKonstantin Belousov upper = 1; 3230e9a2605SKonstantin Belousov case 'x': 3240e9a2605SKonstantin Belousov base = 16; 3250e9a2605SKonstantin Belousov goto handle_nosign; 3260e9a2605SKonstantin Belousov case 'y': 3270e9a2605SKonstantin Belousov base = 16; 3280e9a2605SKonstantin Belousov sign = 1; 3290e9a2605SKonstantin Belousov goto handle_sign; 3300e9a2605SKonstantin Belousov case 'z': 3310e9a2605SKonstantin Belousov zflag = 1; 3320e9a2605SKonstantin Belousov goto reswitch; 3330e9a2605SKonstantin Belousov handle_nosign: 3340e9a2605SKonstantin Belousov sign = 0; 3350e9a2605SKonstantin Belousov if (jflag) 3360e9a2605SKonstantin Belousov num = va_arg(ap, uintmax_t); 3370e9a2605SKonstantin Belousov else if (qflag) 3380e9a2605SKonstantin Belousov num = va_arg(ap, u_quad_t); 3390e9a2605SKonstantin Belousov else if (tflag) 3400e9a2605SKonstantin Belousov num = va_arg(ap, ptrdiff_t); 3410e9a2605SKonstantin Belousov else if (lflag) 3420e9a2605SKonstantin Belousov num = va_arg(ap, u_long); 3430e9a2605SKonstantin Belousov else if (zflag) 3440e9a2605SKonstantin Belousov num = va_arg(ap, size_t); 3450e9a2605SKonstantin Belousov else if (hflag) 3460e9a2605SKonstantin Belousov num = (u_short)va_arg(ap, int); 3470e9a2605SKonstantin Belousov else if (cflag) 3480e9a2605SKonstantin Belousov num = (u_char)va_arg(ap, int); 3490e9a2605SKonstantin Belousov else 3500e9a2605SKonstantin Belousov num = va_arg(ap, u_int); 3510e9a2605SKonstantin Belousov goto number; 3520e9a2605SKonstantin Belousov handle_sign: 3530e9a2605SKonstantin Belousov if (jflag) 3540e9a2605SKonstantin Belousov num = va_arg(ap, intmax_t); 3550e9a2605SKonstantin Belousov else if (qflag) 3560e9a2605SKonstantin Belousov num = va_arg(ap, quad_t); 3570e9a2605SKonstantin Belousov else if (tflag) 3580e9a2605SKonstantin Belousov num = va_arg(ap, ptrdiff_t); 3590e9a2605SKonstantin Belousov else if (lflag) 3600e9a2605SKonstantin Belousov num = va_arg(ap, long); 3610e9a2605SKonstantin Belousov else if (zflag) 3620e9a2605SKonstantin Belousov num = va_arg(ap, ssize_t); 3630e9a2605SKonstantin Belousov else if (hflag) 3640e9a2605SKonstantin Belousov num = (short)va_arg(ap, int); 3650e9a2605SKonstantin Belousov else if (cflag) 3660e9a2605SKonstantin Belousov num = (char)va_arg(ap, int); 3670e9a2605SKonstantin Belousov else 3680e9a2605SKonstantin Belousov num = va_arg(ap, int); 3690e9a2605SKonstantin Belousov number: 3700e9a2605SKonstantin Belousov if (sign && (intmax_t)num < 0) { 3710e9a2605SKonstantin Belousov neg = 1; 3720e9a2605SKonstantin Belousov num = -(intmax_t)num; 3730e9a2605SKonstantin Belousov } 3740e9a2605SKonstantin Belousov p = ksprintn(nbuf, num, base, &n, upper); 3750e9a2605SKonstantin Belousov tmp = 0; 3760e9a2605SKonstantin Belousov if (sharpflag && num != 0) { 3770e9a2605SKonstantin Belousov if (base == 8) 3780e9a2605SKonstantin Belousov tmp++; 3790e9a2605SKonstantin Belousov else if (base == 16) 3800e9a2605SKonstantin Belousov tmp += 2; 3810e9a2605SKonstantin Belousov } 3820e9a2605SKonstantin Belousov if (neg) 3830e9a2605SKonstantin Belousov tmp++; 3840e9a2605SKonstantin Belousov 3850e9a2605SKonstantin Belousov if (!ladjust && padc == '0') 3860e9a2605SKonstantin Belousov dwidth = width - tmp; 3870e9a2605SKonstantin Belousov width -= tmp + imax(dwidth, n); 3880e9a2605SKonstantin Belousov dwidth -= n; 3890e9a2605SKonstantin Belousov if (!ladjust) 3900e9a2605SKonstantin Belousov while (width-- > 0) 3910e9a2605SKonstantin Belousov PCHAR(' '); 3920e9a2605SKonstantin Belousov if (neg) 3930e9a2605SKonstantin Belousov PCHAR('-'); 3940e9a2605SKonstantin Belousov if (sharpflag && num != 0) { 3950e9a2605SKonstantin Belousov if (base == 8) { 3960e9a2605SKonstantin Belousov PCHAR('0'); 3970e9a2605SKonstantin Belousov } else if (base == 16) { 3980e9a2605SKonstantin Belousov PCHAR('0'); 3990e9a2605SKonstantin Belousov PCHAR('x'); 4000e9a2605SKonstantin Belousov } 4010e9a2605SKonstantin Belousov } 4020e9a2605SKonstantin Belousov while (dwidth-- > 0) 4030e9a2605SKonstantin Belousov PCHAR('0'); 4040e9a2605SKonstantin Belousov 4050e9a2605SKonstantin Belousov while (*p) 4060e9a2605SKonstantin Belousov PCHAR(*p--); 4070e9a2605SKonstantin Belousov 4080e9a2605SKonstantin Belousov if (ladjust) 4090e9a2605SKonstantin Belousov while (width-- > 0) 4100e9a2605SKonstantin Belousov PCHAR(' '); 4110e9a2605SKonstantin Belousov 4120e9a2605SKonstantin Belousov break; 4130e9a2605SKonstantin Belousov default: 4140e9a2605SKonstantin Belousov while (percent < fmt) 4150e9a2605SKonstantin Belousov PCHAR(*percent++); 4160e9a2605SKonstantin Belousov /* 4170e9a2605SKonstantin Belousov * Since we ignore an formatting argument it is no 4180e9a2605SKonstantin Belousov * longer safe to obey the remaining formatting 4190e9a2605SKonstantin Belousov * arguments as the arguments will no longer match 4200e9a2605SKonstantin Belousov * the format specs. 4210e9a2605SKonstantin Belousov */ 4220e9a2605SKonstantin Belousov stop = 1; 4230e9a2605SKonstantin Belousov break; 4240e9a2605SKonstantin Belousov } 4250e9a2605SKonstantin Belousov } 4260e9a2605SKonstantin Belousov #undef PCHAR 4270e9a2605SKonstantin Belousov } 4280e9a2605SKonstantin Belousov 4290e9a2605SKonstantin Belousov int 4300e9a2605SKonstantin Belousov rtld_vsnprintf(char *buf, size_t bufsize, const char *fmt, va_list ap) 4310e9a2605SKonstantin Belousov { 4320e9a2605SKonstantin Belousov struct snprintf_arg info; 4330e9a2605SKonstantin Belousov int retval; 4340e9a2605SKonstantin Belousov 435*b2367317SKonstantin Belousov info.method = PRINT_METHOD_SNPRINTF; 4360e9a2605SKonstantin Belousov info.buf = info.str = buf; 4370e9a2605SKonstantin Belousov info.buf_total = info.remain = bufsize; 4380e9a2605SKonstantin Belousov info.fd = -1; 439*b2367317SKonstantin Belousov retval = kvprintf(fmt, &info, 10, ap); 4400e9a2605SKonstantin Belousov if (info.remain >= 1) 4410e9a2605SKonstantin Belousov *info.str++ = '\0'; 4420e9a2605SKonstantin Belousov return (retval); 4430e9a2605SKonstantin Belousov } 4440e9a2605SKonstantin Belousov 4450e9a2605SKonstantin Belousov int 4460e9a2605SKonstantin Belousov rtld_vfdprintf(int fd, const char *fmt, va_list ap) 4470e9a2605SKonstantin Belousov { 4480e9a2605SKonstantin Belousov char buf[512]; 4490e9a2605SKonstantin Belousov struct snprintf_arg info; 4500e9a2605SKonstantin Belousov int retval; 4510e9a2605SKonstantin Belousov 452*b2367317SKonstantin Belousov info.method = PRINT_METHOD_WRITE; 4530e9a2605SKonstantin Belousov info.buf = info.str = buf; 4540e9a2605SKonstantin Belousov info.buf_total = info.remain = sizeof(buf); 4550e9a2605SKonstantin Belousov info.fd = fd; 456*b2367317SKonstantin Belousov retval = kvprintf(fmt, &info, 10, ap); 4570e9a2605SKonstantin Belousov printf_out(&info); 4580e9a2605SKonstantin Belousov return (retval); 4590e9a2605SKonstantin Belousov } 4600e9a2605SKonstantin Belousov 4610e9a2605SKonstantin Belousov int 4620e9a2605SKonstantin Belousov rtld_fdprintf(int fd, const char *fmt, ...) 4630e9a2605SKonstantin Belousov { 4640e9a2605SKonstantin Belousov va_list ap; 4650e9a2605SKonstantin Belousov int retval; 4660e9a2605SKonstantin Belousov 4670e9a2605SKonstantin Belousov va_start(ap, fmt); 4680e9a2605SKonstantin Belousov retval = rtld_vfdprintf(fd, fmt, ap); 4690e9a2605SKonstantin Belousov va_end(ap); 4700e9a2605SKonstantin Belousov return (retval); 4710e9a2605SKonstantin Belousov } 4720e9a2605SKonstantin Belousov 4730e9a2605SKonstantin Belousov void 4740e9a2605SKonstantin Belousov rtld_fdputstr(int fd, const char *str) 4750e9a2605SKonstantin Belousov { 4760e9a2605SKonstantin Belousov 4770e9a2605SKonstantin Belousov write(fd, str, strlen(str)); 4780e9a2605SKonstantin Belousov } 4790e9a2605SKonstantin Belousov 4800e9a2605SKonstantin Belousov void 4810e9a2605SKonstantin Belousov rtld_fdputchar(int fd, int c) 4820e9a2605SKonstantin Belousov { 4830e9a2605SKonstantin Belousov char c1; 4840e9a2605SKonstantin Belousov 4850e9a2605SKonstantin Belousov c1 = c; 4860e9a2605SKonstantin Belousov write(fd, &c1, 1); 4870e9a2605SKonstantin Belousov } 488