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