xref: /minix/external/bsd/bind/dist/lib/lwres/print.c (revision 00b67f09)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: print.c,v 1.6 2014/12/10 04:38:02 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2004, 2005, 2007, 2011, 2012, 2014  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  * Copyright (C) 1999-2001, 2003  Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek  *
7*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek  */
19*00b67f09SDavid van Moolenbroek 
20*00b67f09SDavid van Moolenbroek #include <config.h>
21*00b67f09SDavid van Moolenbroek 
22*00b67f09SDavid van Moolenbroek #include <ctype.h>
23*00b67f09SDavid van Moolenbroek #include <stdio.h>		/* for sprintf */
24*00b67f09SDavid van Moolenbroek #include <string.h>
25*00b67f09SDavid van Moolenbroek 
26*00b67f09SDavid van Moolenbroek #define	LWRES__PRINT_SOURCE	/* Used to get the lwres_print_* prototypes. */
27*00b67f09SDavid van Moolenbroek 
28*00b67f09SDavid van Moolenbroek #include <lwres/stdlib.h>
29*00b67f09SDavid van Moolenbroek #include <lwres/string.h>
30*00b67f09SDavid van Moolenbroek 
31*00b67f09SDavid van Moolenbroek #include "assert_p.h"
32*00b67f09SDavid van Moolenbroek #include "print_p.h"
33*00b67f09SDavid van Moolenbroek 
34*00b67f09SDavid van Moolenbroek #define LWRES_PRINT_QUADFORMAT LWRES_PLATFORM_QUADFORMAT
35*00b67f09SDavid van Moolenbroek 
36*00b67f09SDavid van Moolenbroek int
lwres__print_sprintf(char * str,const char * format,...)37*00b67f09SDavid van Moolenbroek lwres__print_sprintf(char *str, const char *format, ...) {
38*00b67f09SDavid van Moolenbroek 	va_list ap;
39*00b67f09SDavid van Moolenbroek 
40*00b67f09SDavid van Moolenbroek 	va_start(ap, format);
41*00b67f09SDavid van Moolenbroek 	vsprintf(str, format, ap);
42*00b67f09SDavid van Moolenbroek 	va_end(ap);
43*00b67f09SDavid van Moolenbroek 	return (strlen(str));
44*00b67f09SDavid van Moolenbroek }
45*00b67f09SDavid van Moolenbroek 
46*00b67f09SDavid van Moolenbroek /*
47*00b67f09SDavid van Moolenbroek  * Return length of string that would have been written if not truncated.
48*00b67f09SDavid van Moolenbroek  */
49*00b67f09SDavid van Moolenbroek 
50*00b67f09SDavid van Moolenbroek int
lwres__print_snprintf(char * str,size_t size,const char * format,...)51*00b67f09SDavid van Moolenbroek lwres__print_snprintf(char *str, size_t size, const char *format, ...) {
52*00b67f09SDavid van Moolenbroek 	va_list ap;
53*00b67f09SDavid van Moolenbroek 	int ret;
54*00b67f09SDavid van Moolenbroek 
55*00b67f09SDavid van Moolenbroek 	va_start(ap, format);
56*00b67f09SDavid van Moolenbroek 	ret = vsnprintf(str, size, format, ap);
57*00b67f09SDavid van Moolenbroek 	va_end(ap);
58*00b67f09SDavid van Moolenbroek 	return (ret);
59*00b67f09SDavid van Moolenbroek 
60*00b67f09SDavid van Moolenbroek }
61*00b67f09SDavid van Moolenbroek 
62*00b67f09SDavid van Moolenbroek /*
63*00b67f09SDavid van Moolenbroek  * Return length of string that would have been written if not truncated.
64*00b67f09SDavid van Moolenbroek  */
65*00b67f09SDavid van Moolenbroek 
66*00b67f09SDavid van Moolenbroek int
lwres__print_vsnprintf(char * str,size_t size,const char * format,va_list ap)67*00b67f09SDavid van Moolenbroek lwres__print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
68*00b67f09SDavid van Moolenbroek 	int h;
69*00b67f09SDavid van Moolenbroek 	int l;
70*00b67f09SDavid van Moolenbroek 	int q;
71*00b67f09SDavid van Moolenbroek 	int alt;
72*00b67f09SDavid van Moolenbroek 	int zero;
73*00b67f09SDavid van Moolenbroek 	int left;
74*00b67f09SDavid van Moolenbroek 	int plus;
75*00b67f09SDavid van Moolenbroek 	int space;
76*00b67f09SDavid van Moolenbroek 	long long tmpi;
77*00b67f09SDavid van Moolenbroek 	unsigned long long tmpui;
78*00b67f09SDavid van Moolenbroek 	unsigned long width;
79*00b67f09SDavid van Moolenbroek 	unsigned long precision;
80*00b67f09SDavid van Moolenbroek 	unsigned int length;
81*00b67f09SDavid van Moolenbroek 	char buf[1024];
82*00b67f09SDavid van Moolenbroek 	char c;
83*00b67f09SDavid van Moolenbroek 	void *v;
84*00b67f09SDavid van Moolenbroek 	char *save = str;
85*00b67f09SDavid van Moolenbroek 	const char *cp;
86*00b67f09SDavid van Moolenbroek 	const char *head;
87*00b67f09SDavid van Moolenbroek 	int count = 0;
88*00b67f09SDavid van Moolenbroek 	int pad;
89*00b67f09SDavid van Moolenbroek 	int zeropad;
90*00b67f09SDavid van Moolenbroek 	int dot;
91*00b67f09SDavid van Moolenbroek 	double dbl;
92*00b67f09SDavid van Moolenbroek #ifdef HAVE_LONG_DOUBLE
93*00b67f09SDavid van Moolenbroek 	long double ldbl;
94*00b67f09SDavid van Moolenbroek #endif
95*00b67f09SDavid van Moolenbroek 	char fmt[32];
96*00b67f09SDavid van Moolenbroek 
97*00b67f09SDavid van Moolenbroek 	INSIST(str != NULL);
98*00b67f09SDavid van Moolenbroek 	INSIST(format != NULL);
99*00b67f09SDavid van Moolenbroek 
100*00b67f09SDavid van Moolenbroek 	while (*format != '\0') {
101*00b67f09SDavid van Moolenbroek 		if (*format != '%') {
102*00b67f09SDavid van Moolenbroek 			if (size > 1U) {
103*00b67f09SDavid van Moolenbroek 				*str++ = *format;
104*00b67f09SDavid van Moolenbroek 				size--;
105*00b67f09SDavid van Moolenbroek 			}
106*00b67f09SDavid van Moolenbroek 			count++;
107*00b67f09SDavid van Moolenbroek 			format++;
108*00b67f09SDavid van Moolenbroek 			continue;
109*00b67f09SDavid van Moolenbroek 		}
110*00b67f09SDavid van Moolenbroek 		format++;
111*00b67f09SDavid van Moolenbroek 
112*00b67f09SDavid van Moolenbroek 		/*
113*00b67f09SDavid van Moolenbroek 		 * Reset flags.
114*00b67f09SDavid van Moolenbroek 		 */
115*00b67f09SDavid van Moolenbroek 		dot = space = plus = left = zero = alt = h = l = q = 0;
116*00b67f09SDavid van Moolenbroek 		width = precision = 0;
117*00b67f09SDavid van Moolenbroek 		head = "";
118*00b67f09SDavid van Moolenbroek 		length = pad = zeropad = 0;
119*00b67f09SDavid van Moolenbroek 		POST(length);
120*00b67f09SDavid van Moolenbroek 
121*00b67f09SDavid van Moolenbroek 		do {
122*00b67f09SDavid van Moolenbroek 			if (*format == '#') {
123*00b67f09SDavid van Moolenbroek 				alt = 1;
124*00b67f09SDavid van Moolenbroek 				format++;
125*00b67f09SDavid van Moolenbroek 			} else if (*format == '-') {
126*00b67f09SDavid van Moolenbroek 				left = 1;
127*00b67f09SDavid van Moolenbroek 				zero = 0;
128*00b67f09SDavid van Moolenbroek 				format++;
129*00b67f09SDavid van Moolenbroek 			} else if (*format == ' ') {
130*00b67f09SDavid van Moolenbroek 				if (!plus)
131*00b67f09SDavid van Moolenbroek 					space = 1;
132*00b67f09SDavid van Moolenbroek 				format++;
133*00b67f09SDavid van Moolenbroek 			} else if (*format == '+') {
134*00b67f09SDavid van Moolenbroek 				plus = 1;
135*00b67f09SDavid van Moolenbroek 				space = 0;
136*00b67f09SDavid van Moolenbroek 				format++;
137*00b67f09SDavid van Moolenbroek 			} else if (*format == '0') {
138*00b67f09SDavid van Moolenbroek 				if (!left)
139*00b67f09SDavid van Moolenbroek 					zero = 1;
140*00b67f09SDavid van Moolenbroek 				format++;
141*00b67f09SDavid van Moolenbroek 			} else
142*00b67f09SDavid van Moolenbroek 				break;
143*00b67f09SDavid van Moolenbroek 		} while (1);
144*00b67f09SDavid van Moolenbroek 
145*00b67f09SDavid van Moolenbroek 		/*
146*00b67f09SDavid van Moolenbroek 		 * Width.
147*00b67f09SDavid van Moolenbroek 		 */
148*00b67f09SDavid van Moolenbroek 		if (*format == '*') {
149*00b67f09SDavid van Moolenbroek 			width = va_arg(ap, int);
150*00b67f09SDavid van Moolenbroek 			format++;
151*00b67f09SDavid van Moolenbroek 		} else if (isdigit((unsigned char)*format)) {
152*00b67f09SDavid van Moolenbroek 			char *e;
153*00b67f09SDavid van Moolenbroek 			width = strtoul(format, &e, 10);
154*00b67f09SDavid van Moolenbroek 			format = e;
155*00b67f09SDavid van Moolenbroek 		}
156*00b67f09SDavid van Moolenbroek 
157*00b67f09SDavid van Moolenbroek 		/*
158*00b67f09SDavid van Moolenbroek 		 * Precision.
159*00b67f09SDavid van Moolenbroek 		 */
160*00b67f09SDavid van Moolenbroek 		if (*format == '.') {
161*00b67f09SDavid van Moolenbroek 			format++;
162*00b67f09SDavid van Moolenbroek 			dot = 1;
163*00b67f09SDavid van Moolenbroek 			if (*format == '*') {
164*00b67f09SDavid van Moolenbroek 				precision = va_arg(ap, int);
165*00b67f09SDavid van Moolenbroek 				format++;
166*00b67f09SDavid van Moolenbroek 			} else if (isdigit((unsigned char)*format)) {
167*00b67f09SDavid van Moolenbroek 				char *e;
168*00b67f09SDavid van Moolenbroek 				precision = strtoul(format, &e, 10);
169*00b67f09SDavid van Moolenbroek 				format = e;
170*00b67f09SDavid van Moolenbroek 			}
171*00b67f09SDavid van Moolenbroek 		}
172*00b67f09SDavid van Moolenbroek 
173*00b67f09SDavid van Moolenbroek 		switch (*format) {
174*00b67f09SDavid van Moolenbroek 		case '\0':
175*00b67f09SDavid van Moolenbroek 			continue;
176*00b67f09SDavid van Moolenbroek 		case '%':
177*00b67f09SDavid van Moolenbroek 			if (size > 1U) {
178*00b67f09SDavid van Moolenbroek 				*str++ = *format;
179*00b67f09SDavid van Moolenbroek 				size--;
180*00b67f09SDavid van Moolenbroek 			}
181*00b67f09SDavid van Moolenbroek 			count++;
182*00b67f09SDavid van Moolenbroek 			break;
183*00b67f09SDavid van Moolenbroek 		case 'q':
184*00b67f09SDavid van Moolenbroek 			q = 1;
185*00b67f09SDavid van Moolenbroek 			format++;
186*00b67f09SDavid van Moolenbroek 			goto doint;
187*00b67f09SDavid van Moolenbroek 		case 'h':
188*00b67f09SDavid van Moolenbroek 			h = 1;
189*00b67f09SDavid van Moolenbroek 			format++;
190*00b67f09SDavid van Moolenbroek 			goto doint;
191*00b67f09SDavid van Moolenbroek 		case 'l':
192*00b67f09SDavid van Moolenbroek 			l = 1;
193*00b67f09SDavid van Moolenbroek 			format++;
194*00b67f09SDavid van Moolenbroek 			if (*format == 'l') {
195*00b67f09SDavid van Moolenbroek 				q = 1;
196*00b67f09SDavid van Moolenbroek 				format++;
197*00b67f09SDavid van Moolenbroek 			}
198*00b67f09SDavid van Moolenbroek 			goto doint;
199*00b67f09SDavid van Moolenbroek 		case 'n':
200*00b67f09SDavid van Moolenbroek 		case 'i':
201*00b67f09SDavid van Moolenbroek 		case 'd':
202*00b67f09SDavid van Moolenbroek 		case 'o':
203*00b67f09SDavid van Moolenbroek 		case 'u':
204*00b67f09SDavid van Moolenbroek 		case 'x':
205*00b67f09SDavid van Moolenbroek 		case 'X':
206*00b67f09SDavid van Moolenbroek 		doint:
207*00b67f09SDavid van Moolenbroek 			if (precision != 0U)
208*00b67f09SDavid van Moolenbroek 				zero = 0;
209*00b67f09SDavid van Moolenbroek 			switch (*format) {
210*00b67f09SDavid van Moolenbroek 			case 'n':
211*00b67f09SDavid van Moolenbroek 				if (h) {
212*00b67f09SDavid van Moolenbroek 					short int *p;
213*00b67f09SDavid van Moolenbroek 					p = va_arg(ap, short *);
214*00b67f09SDavid van Moolenbroek 					REQUIRE(p != NULL);
215*00b67f09SDavid van Moolenbroek 					*p = str - save;
216*00b67f09SDavid van Moolenbroek 				} else if (l) {
217*00b67f09SDavid van Moolenbroek 					long int *p;
218*00b67f09SDavid van Moolenbroek 					p = va_arg(ap, long *);
219*00b67f09SDavid van Moolenbroek 					REQUIRE(p != NULL);
220*00b67f09SDavid van Moolenbroek 					*p = str - save;
221*00b67f09SDavid van Moolenbroek 				} else {
222*00b67f09SDavid van Moolenbroek 					int *p;
223*00b67f09SDavid van Moolenbroek 					p = va_arg(ap, int *);
224*00b67f09SDavid van Moolenbroek 					REQUIRE(p != NULL);
225*00b67f09SDavid van Moolenbroek 					*p = str - save;
226*00b67f09SDavid van Moolenbroek 				}
227*00b67f09SDavid van Moolenbroek 				break;
228*00b67f09SDavid van Moolenbroek 			case 'i':
229*00b67f09SDavid van Moolenbroek 			case 'd':
230*00b67f09SDavid van Moolenbroek 				if (q)
231*00b67f09SDavid van Moolenbroek 					tmpi = va_arg(ap, long long int);
232*00b67f09SDavid van Moolenbroek 				else if (l)
233*00b67f09SDavid van Moolenbroek 					tmpi = va_arg(ap, long int);
234*00b67f09SDavid van Moolenbroek 				else
235*00b67f09SDavid van Moolenbroek 					tmpi = va_arg(ap, int);
236*00b67f09SDavid van Moolenbroek 				if (tmpi < 0) {
237*00b67f09SDavid van Moolenbroek 					head = "-";
238*00b67f09SDavid van Moolenbroek 					tmpui = -tmpi;
239*00b67f09SDavid van Moolenbroek 				} else {
240*00b67f09SDavid van Moolenbroek 					if (plus)
241*00b67f09SDavid van Moolenbroek 						head = "+";
242*00b67f09SDavid van Moolenbroek 					else if (space)
243*00b67f09SDavid van Moolenbroek 						head = " ";
244*00b67f09SDavid van Moolenbroek 					else
245*00b67f09SDavid van Moolenbroek 						head = "";
246*00b67f09SDavid van Moolenbroek 					tmpui = tmpi;
247*00b67f09SDavid van Moolenbroek 				}
248*00b67f09SDavid van Moolenbroek 				sprintf(buf, "%" LWRES_PRINT_QUADFORMAT "u",
249*00b67f09SDavid van Moolenbroek 					tmpui);
250*00b67f09SDavid van Moolenbroek 				goto printint;
251*00b67f09SDavid van Moolenbroek 			case 'o':
252*00b67f09SDavid van Moolenbroek 				if (q)
253*00b67f09SDavid van Moolenbroek 					tmpui = va_arg(ap,
254*00b67f09SDavid van Moolenbroek 						       unsigned long long int);
255*00b67f09SDavid van Moolenbroek 				else if (l)
256*00b67f09SDavid van Moolenbroek 					tmpui = va_arg(ap, long int);
257*00b67f09SDavid van Moolenbroek 				else
258*00b67f09SDavid van Moolenbroek 					tmpui = va_arg(ap, int);
259*00b67f09SDavid van Moolenbroek 				sprintf(buf,
260*00b67f09SDavid van Moolenbroek 					alt ? "%#" LWRES_PRINT_QUADFORMAT "o"
261*00b67f09SDavid van Moolenbroek 					    : "%" LWRES_PRINT_QUADFORMAT "o",
262*00b67f09SDavid van Moolenbroek 					tmpui);
263*00b67f09SDavid van Moolenbroek 				goto printint;
264*00b67f09SDavid van Moolenbroek 			case 'u':
265*00b67f09SDavid van Moolenbroek 				if (q)
266*00b67f09SDavid van Moolenbroek 					tmpui = va_arg(ap,
267*00b67f09SDavid van Moolenbroek 						       unsigned long long int);
268*00b67f09SDavid van Moolenbroek 				else if (l)
269*00b67f09SDavid van Moolenbroek 					tmpui = va_arg(ap, unsigned long int);
270*00b67f09SDavid van Moolenbroek 				else
271*00b67f09SDavid van Moolenbroek 					tmpui = va_arg(ap, unsigned int);
272*00b67f09SDavid van Moolenbroek 				sprintf(buf, "%" LWRES_PRINT_QUADFORMAT "u",
273*00b67f09SDavid van Moolenbroek 					tmpui);
274*00b67f09SDavid van Moolenbroek 				goto printint;
275*00b67f09SDavid van Moolenbroek 			case 'x':
276*00b67f09SDavid van Moolenbroek 				if (q)
277*00b67f09SDavid van Moolenbroek 					tmpui = va_arg(ap,
278*00b67f09SDavid van Moolenbroek 						       unsigned long long int);
279*00b67f09SDavid van Moolenbroek 				else if (l)
280*00b67f09SDavid van Moolenbroek 					tmpui = va_arg(ap, unsigned long int);
281*00b67f09SDavid van Moolenbroek 				else
282*00b67f09SDavid van Moolenbroek 					tmpui = va_arg(ap, unsigned int);
283*00b67f09SDavid van Moolenbroek 				if (alt) {
284*00b67f09SDavid van Moolenbroek 					head = "0x";
285*00b67f09SDavid van Moolenbroek 					if (precision > 2U)
286*00b67f09SDavid van Moolenbroek 						precision -= 2;
287*00b67f09SDavid van Moolenbroek 				}
288*00b67f09SDavid van Moolenbroek 				sprintf(buf, "%" LWRES_PRINT_QUADFORMAT "x",
289*00b67f09SDavid van Moolenbroek 					tmpui);
290*00b67f09SDavid van Moolenbroek 				goto printint;
291*00b67f09SDavid van Moolenbroek 			case 'X':
292*00b67f09SDavid van Moolenbroek 				if (q)
293*00b67f09SDavid van Moolenbroek 					tmpui = va_arg(ap,
294*00b67f09SDavid van Moolenbroek 						       unsigned long long int);
295*00b67f09SDavid van Moolenbroek 				else if (l)
296*00b67f09SDavid van Moolenbroek 					tmpui = va_arg(ap, unsigned long int);
297*00b67f09SDavid van Moolenbroek 				else
298*00b67f09SDavid van Moolenbroek 					tmpui = va_arg(ap, unsigned int);
299*00b67f09SDavid van Moolenbroek 				if (alt) {
300*00b67f09SDavid van Moolenbroek 					head = "0X";
301*00b67f09SDavid van Moolenbroek 					if (precision > 2U)
302*00b67f09SDavid van Moolenbroek 						precision -= 2;
303*00b67f09SDavid van Moolenbroek 				}
304*00b67f09SDavid van Moolenbroek 				sprintf(buf, "%" LWRES_PRINT_QUADFORMAT "X",
305*00b67f09SDavid van Moolenbroek 					tmpui);
306*00b67f09SDavid van Moolenbroek 				goto printint;
307*00b67f09SDavid van Moolenbroek 			printint:
308*00b67f09SDavid van Moolenbroek 				if (precision != 0U || width != 0U) {
309*00b67f09SDavid van Moolenbroek 					length = strlen(buf);
310*00b67f09SDavid van Moolenbroek 					if (length < precision)
311*00b67f09SDavid van Moolenbroek 						zeropad = precision - length;
312*00b67f09SDavid van Moolenbroek 					else if (length < width && zero)
313*00b67f09SDavid van Moolenbroek 						zeropad = width - length;
314*00b67f09SDavid van Moolenbroek 					if (width != 0U) {
315*00b67f09SDavid van Moolenbroek 						pad = width - length -
316*00b67f09SDavid van Moolenbroek 						      zeropad - strlen(head);
317*00b67f09SDavid van Moolenbroek 						if (pad < 0)
318*00b67f09SDavid van Moolenbroek 							pad = 0;
319*00b67f09SDavid van Moolenbroek 					}
320*00b67f09SDavid van Moolenbroek 				}
321*00b67f09SDavid van Moolenbroek 				count += strlen(head) + strlen(buf) + pad +
322*00b67f09SDavid van Moolenbroek 					 zeropad;
323*00b67f09SDavid van Moolenbroek 				if (!left) {
324*00b67f09SDavid van Moolenbroek 					while (pad > 0 && size > 1U) {
325*00b67f09SDavid van Moolenbroek 						*str++ = ' ';
326*00b67f09SDavid van Moolenbroek 						size--;
327*00b67f09SDavid van Moolenbroek 						pad--;
328*00b67f09SDavid van Moolenbroek 					}
329*00b67f09SDavid van Moolenbroek 				}
330*00b67f09SDavid van Moolenbroek 				cp = head;
331*00b67f09SDavid van Moolenbroek 				while (*cp != '\0' && size > 1U) {
332*00b67f09SDavid van Moolenbroek 					*str++ = *cp++;
333*00b67f09SDavid van Moolenbroek 					size--;
334*00b67f09SDavid van Moolenbroek 				}
335*00b67f09SDavid van Moolenbroek 				while (zeropad > 0 && size > 1U) {
336*00b67f09SDavid van Moolenbroek 					*str++ = '0';
337*00b67f09SDavid van Moolenbroek 					size--;
338*00b67f09SDavid van Moolenbroek 					zeropad--;
339*00b67f09SDavid van Moolenbroek 				}
340*00b67f09SDavid van Moolenbroek 				cp = buf;
341*00b67f09SDavid van Moolenbroek 				while (*cp != '\0' && size > 1U) {
342*00b67f09SDavid van Moolenbroek 					*str++ = *cp++;
343*00b67f09SDavid van Moolenbroek 					size--;
344*00b67f09SDavid van Moolenbroek 				}
345*00b67f09SDavid van Moolenbroek 				while (pad > 0 && size > 1U) {
346*00b67f09SDavid van Moolenbroek 					*str++ = ' ';
347*00b67f09SDavid van Moolenbroek 					size--;
348*00b67f09SDavid van Moolenbroek 					pad--;
349*00b67f09SDavid van Moolenbroek 				}
350*00b67f09SDavid van Moolenbroek 				break;
351*00b67f09SDavid van Moolenbroek 			default:
352*00b67f09SDavid van Moolenbroek 				break;
353*00b67f09SDavid van Moolenbroek 			}
354*00b67f09SDavid van Moolenbroek 			break;
355*00b67f09SDavid van Moolenbroek 		case 's':
356*00b67f09SDavid van Moolenbroek 			cp = va_arg(ap, char *);
357*00b67f09SDavid van Moolenbroek 			REQUIRE(cp != NULL);
358*00b67f09SDavid van Moolenbroek 
359*00b67f09SDavid van Moolenbroek 			if (precision != 0U) {
360*00b67f09SDavid van Moolenbroek 				/*
361*00b67f09SDavid van Moolenbroek 				 * cp need not be NULL terminated.
362*00b67f09SDavid van Moolenbroek 				 */
363*00b67f09SDavid van Moolenbroek 				const char *tp;
364*00b67f09SDavid van Moolenbroek 				unsigned long n;
365*00b67f09SDavid van Moolenbroek 
366*00b67f09SDavid van Moolenbroek 				n = precision;
367*00b67f09SDavid van Moolenbroek 				tp = cp;
368*00b67f09SDavid van Moolenbroek 				while (n != 0U && *tp != '\0')
369*00b67f09SDavid van Moolenbroek 					n--, tp++;
370*00b67f09SDavid van Moolenbroek 				length = precision - n;
371*00b67f09SDavid van Moolenbroek 			} else {
372*00b67f09SDavid van Moolenbroek 				length = strlen(cp);
373*00b67f09SDavid van Moolenbroek 			}
374*00b67f09SDavid van Moolenbroek 			if (width != 0U) {
375*00b67f09SDavid van Moolenbroek 				pad = width - length;
376*00b67f09SDavid van Moolenbroek 				if (pad < 0)
377*00b67f09SDavid van Moolenbroek 					pad = 0;
378*00b67f09SDavid van Moolenbroek 			}
379*00b67f09SDavid van Moolenbroek 			count += pad + length;
380*00b67f09SDavid van Moolenbroek 			if (!left)
381*00b67f09SDavid van Moolenbroek 				while (pad > 0 && size > 1U) {
382*00b67f09SDavid van Moolenbroek 					*str++ = ' ';
383*00b67f09SDavid van Moolenbroek 					size--;
384*00b67f09SDavid van Moolenbroek 					pad--;
385*00b67f09SDavid van Moolenbroek 				}
386*00b67f09SDavid van Moolenbroek 			if (precision != 0U)
387*00b67f09SDavid van Moolenbroek 				while (precision > 0U && *cp != '\0' &&
388*00b67f09SDavid van Moolenbroek 				       size > 1U) {
389*00b67f09SDavid van Moolenbroek 					*str++ = *cp++;
390*00b67f09SDavid van Moolenbroek 					size--;
391*00b67f09SDavid van Moolenbroek 					precision--;
392*00b67f09SDavid van Moolenbroek 				}
393*00b67f09SDavid van Moolenbroek 			else
394*00b67f09SDavid van Moolenbroek 				while (*cp != '\0' && size > 1U) {
395*00b67f09SDavid van Moolenbroek 					*str++ = *cp++;
396*00b67f09SDavid van Moolenbroek 					size--;
397*00b67f09SDavid van Moolenbroek 				}
398*00b67f09SDavid van Moolenbroek 			while (pad > 0 && size > 1U) {
399*00b67f09SDavid van Moolenbroek 				*str++ = ' ';
400*00b67f09SDavid van Moolenbroek 				size--;
401*00b67f09SDavid van Moolenbroek 				pad--;
402*00b67f09SDavid van Moolenbroek 			}
403*00b67f09SDavid van Moolenbroek 			break;
404*00b67f09SDavid van Moolenbroek 		case 'c':
405*00b67f09SDavid van Moolenbroek 			c = va_arg(ap, int);
406*00b67f09SDavid van Moolenbroek 			if (width > 0U) {
407*00b67f09SDavid van Moolenbroek 				count += width;
408*00b67f09SDavid van Moolenbroek 				width--;
409*00b67f09SDavid van Moolenbroek 				if (left) {
410*00b67f09SDavid van Moolenbroek 					*str++ = c;
411*00b67f09SDavid van Moolenbroek 					size--;
412*00b67f09SDavid van Moolenbroek 				}
413*00b67f09SDavid van Moolenbroek 				while (width-- > 0U && size > 1U) {
414*00b67f09SDavid van Moolenbroek 					*str++ = ' ';
415*00b67f09SDavid van Moolenbroek 					size--;
416*00b67f09SDavid van Moolenbroek 				}
417*00b67f09SDavid van Moolenbroek 				if (!left && size > 1U) {
418*00b67f09SDavid van Moolenbroek 					*str++ = c;
419*00b67f09SDavid van Moolenbroek 					size--;
420*00b67f09SDavid van Moolenbroek 				}
421*00b67f09SDavid van Moolenbroek 			} else {
422*00b67f09SDavid van Moolenbroek 				count++;
423*00b67f09SDavid van Moolenbroek 				if (size > 1U) {
424*00b67f09SDavid van Moolenbroek 					*str++ = c;
425*00b67f09SDavid van Moolenbroek 					size--;
426*00b67f09SDavid van Moolenbroek 				}
427*00b67f09SDavid van Moolenbroek 			}
428*00b67f09SDavid van Moolenbroek 			break;
429*00b67f09SDavid van Moolenbroek 		case 'p':
430*00b67f09SDavid van Moolenbroek 			v = va_arg(ap, void *);
431*00b67f09SDavid van Moolenbroek 			sprintf(buf, "%p", v);
432*00b67f09SDavid van Moolenbroek 			length = strlen(buf);
433*00b67f09SDavid van Moolenbroek 			if (precision > length)
434*00b67f09SDavid van Moolenbroek 				zeropad = precision - length;
435*00b67f09SDavid van Moolenbroek 			if (width > 0U) {
436*00b67f09SDavid van Moolenbroek 				pad = width - length - zeropad;
437*00b67f09SDavid van Moolenbroek 				if (pad < 0)
438*00b67f09SDavid van Moolenbroek 					pad = 0;
439*00b67f09SDavid van Moolenbroek 			}
440*00b67f09SDavid van Moolenbroek 			count += length + pad + zeropad;
441*00b67f09SDavid van Moolenbroek 			if (!left)
442*00b67f09SDavid van Moolenbroek 				while (pad > 0 && size > 1U) {
443*00b67f09SDavid van Moolenbroek 					*str++ = ' ';
444*00b67f09SDavid van Moolenbroek 					size--;
445*00b67f09SDavid van Moolenbroek 					pad--;
446*00b67f09SDavid van Moolenbroek 				}
447*00b67f09SDavid van Moolenbroek 			cp = buf;
448*00b67f09SDavid van Moolenbroek 			if (zeropad > 0 && buf[0] == '0' &&
449*00b67f09SDavid van Moolenbroek 			    (buf[1] == 'x' || buf[1] == 'X')) {
450*00b67f09SDavid van Moolenbroek 				if (size > 1U) {
451*00b67f09SDavid van Moolenbroek 					*str++ = *cp++;
452*00b67f09SDavid van Moolenbroek 					size--;
453*00b67f09SDavid van Moolenbroek 				}
454*00b67f09SDavid van Moolenbroek 				if (size > 1U) {
455*00b67f09SDavid van Moolenbroek 					*str++ = *cp++;
456*00b67f09SDavid van Moolenbroek 					size--;
457*00b67f09SDavid van Moolenbroek 				}
458*00b67f09SDavid van Moolenbroek 				while (zeropad > 0 && size > 1U) {
459*00b67f09SDavid van Moolenbroek 					*str++ = '0';
460*00b67f09SDavid van Moolenbroek 					size--;
461*00b67f09SDavid van Moolenbroek 					zeropad--;
462*00b67f09SDavid van Moolenbroek 				}
463*00b67f09SDavid van Moolenbroek 			}
464*00b67f09SDavid van Moolenbroek 			while (*cp != '\0' && size > 1U) {
465*00b67f09SDavid van Moolenbroek 				*str++ = *cp++;
466*00b67f09SDavid van Moolenbroek 				size--;
467*00b67f09SDavid van Moolenbroek 			}
468*00b67f09SDavid van Moolenbroek 			while (pad > 0 && size > 1U) {
469*00b67f09SDavid van Moolenbroek 				*str++ = ' ';
470*00b67f09SDavid van Moolenbroek 				size--;
471*00b67f09SDavid van Moolenbroek 				pad--;
472*00b67f09SDavid van Moolenbroek 			}
473*00b67f09SDavid van Moolenbroek 			break;
474*00b67f09SDavid van Moolenbroek 
475*00b67f09SDavid van Moolenbroek 		case 'D':	/*deprecated*/
476*00b67f09SDavid van Moolenbroek 			INSIST("use %ld instead of %D" == NULL);
477*00b67f09SDavid van Moolenbroek 			break;
478*00b67f09SDavid van Moolenbroek 		case 'O':	/*deprecated*/
479*00b67f09SDavid van Moolenbroek 			INSIST("use %lo instead of %O" == NULL);
480*00b67f09SDavid van Moolenbroek 			break;
481*00b67f09SDavid van Moolenbroek 		case 'U':	/*deprecated*/
482*00b67f09SDavid van Moolenbroek 			INSIST("use %lu instead of %U" == NULL);
483*00b67f09SDavid van Moolenbroek 			break;
484*00b67f09SDavid van Moolenbroek 
485*00b67f09SDavid van Moolenbroek 		case 'L':
486*00b67f09SDavid van Moolenbroek #ifdef HAVE_LONG_DOUBLE
487*00b67f09SDavid van Moolenbroek 			l = 1;
488*00b67f09SDavid van Moolenbroek #else
489*00b67f09SDavid van Moolenbroek 			INSIST("long doubles are not supported" == NULL);
490*00b67f09SDavid van Moolenbroek #endif
491*00b67f09SDavid van Moolenbroek 			/*FALLTHROUGH*/
492*00b67f09SDavid van Moolenbroek 		case 'e':
493*00b67f09SDavid van Moolenbroek 		case 'E':
494*00b67f09SDavid van Moolenbroek 		case 'f':
495*00b67f09SDavid van Moolenbroek 		case 'g':
496*00b67f09SDavid van Moolenbroek 		case 'G':
497*00b67f09SDavid van Moolenbroek 			if (!dot)
498*00b67f09SDavid van Moolenbroek 				precision = 6;
499*00b67f09SDavid van Moolenbroek 			/*
500*00b67f09SDavid van Moolenbroek 			 * IEEE floating point.
501*00b67f09SDavid van Moolenbroek 			 * MIN 2.2250738585072014E-308
502*00b67f09SDavid van Moolenbroek 			 * MAX 1.7976931348623157E+308
503*00b67f09SDavid van Moolenbroek 			 * VAX floating point has a smaller range than IEEE.
504*00b67f09SDavid van Moolenbroek 			 *
505*00b67f09SDavid van Moolenbroek 			 * precisions > 324 don't make much sense.
506*00b67f09SDavid van Moolenbroek 			 * if we cap the precision at 512 we will not
507*00b67f09SDavid van Moolenbroek 			 * overflow buf.
508*00b67f09SDavid van Moolenbroek 			 */
509*00b67f09SDavid van Moolenbroek 			if (precision > 512U)
510*00b67f09SDavid van Moolenbroek 				precision = 512;
511*00b67f09SDavid van Moolenbroek 			sprintf(fmt, "%%%s%s.%lu%s%c", alt ? "#" : "",
512*00b67f09SDavid van Moolenbroek 				plus ? "+" : space ? " " : "",
513*00b67f09SDavid van Moolenbroek 				precision, l ? "L" : "", *format);
514*00b67f09SDavid van Moolenbroek 			switch (*format) {
515*00b67f09SDavid van Moolenbroek 			case 'e':
516*00b67f09SDavid van Moolenbroek 			case 'E':
517*00b67f09SDavid van Moolenbroek 			case 'f':
518*00b67f09SDavid van Moolenbroek 			case 'g':
519*00b67f09SDavid van Moolenbroek 			case 'G':
520*00b67f09SDavid van Moolenbroek #ifdef HAVE_LONG_DOUBLE
521*00b67f09SDavid van Moolenbroek 				if (l) {
522*00b67f09SDavid van Moolenbroek 					ldbl = va_arg(ap, long double);
523*00b67f09SDavid van Moolenbroek 					sprintf(buf, fmt, ldbl);
524*00b67f09SDavid van Moolenbroek 				} else
525*00b67f09SDavid van Moolenbroek #endif
526*00b67f09SDavid van Moolenbroek 				{
527*00b67f09SDavid van Moolenbroek 					dbl = va_arg(ap, double);
528*00b67f09SDavid van Moolenbroek 					sprintf(buf, fmt, dbl);
529*00b67f09SDavid van Moolenbroek 				}
530*00b67f09SDavid van Moolenbroek 				length = strlen(buf);
531*00b67f09SDavid van Moolenbroek 				if (width > 0U) {
532*00b67f09SDavid van Moolenbroek 					pad = width - length;
533*00b67f09SDavid van Moolenbroek 					if (pad < 0)
534*00b67f09SDavid van Moolenbroek 						pad = 0;
535*00b67f09SDavid van Moolenbroek 				}
536*00b67f09SDavid van Moolenbroek 				count += length + pad;
537*00b67f09SDavid van Moolenbroek 				if (!left)
538*00b67f09SDavid van Moolenbroek 					while (pad > 0 && size > 1U) {
539*00b67f09SDavid van Moolenbroek 						*str++ = ' ';
540*00b67f09SDavid van Moolenbroek 						size--;
541*00b67f09SDavid van Moolenbroek 						pad--;
542*00b67f09SDavid van Moolenbroek 					}
543*00b67f09SDavid van Moolenbroek 				cp = buf;
544*00b67f09SDavid van Moolenbroek 				while (*cp != ' ' && size > 1U) {
545*00b67f09SDavid van Moolenbroek 					*str++ = *cp++;
546*00b67f09SDavid van Moolenbroek 					size--;
547*00b67f09SDavid van Moolenbroek 				}
548*00b67f09SDavid van Moolenbroek 				while (pad > 0 && size > 1U) {
549*00b67f09SDavid van Moolenbroek 					*str++ = ' ';
550*00b67f09SDavid van Moolenbroek 					size--;
551*00b67f09SDavid van Moolenbroek 					pad--;
552*00b67f09SDavid van Moolenbroek 				}
553*00b67f09SDavid van Moolenbroek 				break;
554*00b67f09SDavid van Moolenbroek 			default:
555*00b67f09SDavid van Moolenbroek 				continue;
556*00b67f09SDavid van Moolenbroek 			}
557*00b67f09SDavid van Moolenbroek 			break;
558*00b67f09SDavid van Moolenbroek 		default:
559*00b67f09SDavid van Moolenbroek 			continue;
560*00b67f09SDavid van Moolenbroek 		}
561*00b67f09SDavid van Moolenbroek 		format++;
562*00b67f09SDavid van Moolenbroek 	}
563*00b67f09SDavid van Moolenbroek 	if (size > 0U)
564*00b67f09SDavid van Moolenbroek 		*str = '\0';
565*00b67f09SDavid van Moolenbroek 	return (count);
566*00b67f09SDavid van Moolenbroek }
567