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