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