1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1990, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Chris Torek.
9 *
10 * Copyright (c) 2011 The FreeBSD Foundation
11 * All rights reserved.
12 * Portions of this software were developed by David Chisnall
13 * under sponsorship from the FreeBSD Foundation.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 *    notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 *    notice, this list of conditions and the following disclaimer in the
22 *    documentation and/or other materials provided with the distribution.
23 * 3. Neither the name of the University nor the names of its contributors
24 *    may be used to endorse or promote products derived from this software
25 *    without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 * $FreeBSD$
40 */
41
42/*
43 * This file defines common routines used by both printf and wprintf.
44 * You must define CHAR to either char or wchar_t prior to including this.
45 */
46
47
48#ifndef NO_FLOATING_POINT
49
50#define	dtoa		__dtoa
51#define	freedtoa	__freedtoa
52
53#include <float.h>
54#include <math.h>
55#include "floatio.h"
56#include "gdtoa.h"
57
58#define	DEFPREC		6
59
60static int exponent(CHAR *, int, CHAR);
61
62#endif /* !NO_FLOATING_POINT */
63
64static CHAR	*__ujtoa(uintmax_t, CHAR *, int, int, const char *);
65static CHAR	*__ultoa(u_long, CHAR *, int, int, const char *);
66
67#define NIOV 8
68struct io_state {
69	FILE *fp;
70	struct __suio uio;	/* output information: summary */
71	struct __siov iov[NIOV];/* ... and individual io vectors */
72};
73
74static inline void
75io_init(struct io_state *iop, FILE *fp)
76{
77
78	iop->uio.uio_iov = iop->iov;
79	iop->uio.uio_resid = 0;
80	iop->uio.uio_iovcnt = 0;
81	iop->fp = fp;
82}
83
84/*
85 * WARNING: The buffer passed to io_print() is not copied immediately; it must
86 * remain valid until io_flush() is called.
87 */
88static inline int
89io_print(struct io_state *iop, const CHAR * __restrict ptr, int len, locale_t locale)
90{
91
92	iop->iov[iop->uio.uio_iovcnt].iov_base = (char *)ptr;
93	iop->iov[iop->uio.uio_iovcnt].iov_len = len;
94	iop->uio.uio_resid += len;
95	if (++iop->uio.uio_iovcnt >= NIOV)
96		return (__sprint(iop->fp, &iop->uio, locale));
97	else
98		return (0);
99}
100
101/*
102 * Choose PADSIZE to trade efficiency vs. size.  If larger printf
103 * fields occur frequently, increase PADSIZE and make the initialisers
104 * below longer.
105 */
106#define	PADSIZE	16		/* pad chunk size */
107static const CHAR blanks[PADSIZE] =
108{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
109static const CHAR zeroes[PADSIZE] =
110{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
111
112/*
113 * Pad with blanks or zeroes. 'with' should point to either the blanks array
114 * or the zeroes array.
115 */
116static inline int
117io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with,
118		locale_t locale)
119{
120	int n;
121
122	while (howmany > 0) {
123		n = (howmany >= PADSIZE) ? PADSIZE : howmany;
124		if (io_print(iop, with, n, locale))
125			return (-1);
126		howmany -= n;
127	}
128	return (0);
129}
130
131/*
132 * Print exactly len characters of the string spanning p to ep, truncating
133 * or padding with 'with' as necessary.
134 */
135static inline int
136io_printandpad(struct io_state *iop, const CHAR *p, const CHAR *ep,
137	       int len, const CHAR * __restrict with, locale_t locale)
138{
139	int p_len;
140
141	p_len = ep - p;
142	if (p_len > len)
143		p_len = len;
144	if (p_len > 0) {
145		if (io_print(iop, p, p_len, locale))
146			return (-1);
147	} else {
148		p_len = 0;
149	}
150	return (io_pad(iop, len - p_len, with, locale));
151}
152
153static inline int
154io_flush(struct io_state *iop, locale_t locale)
155{
156
157	return (__sprint(iop->fp, &iop->uio, locale));
158}
159
160/*
161 * Convert an unsigned long to ASCII for printf purposes, returning
162 * a pointer to the first character of the string representation.
163 * Octal numbers can be forced to have a leading zero; hex numbers
164 * use the given digits.
165 */
166static CHAR *
167__ultoa(u_long val, CHAR *endp, int base, int octzero, const char *xdigs)
168{
169	CHAR *cp = endp;
170	long sval;
171
172	/*
173	 * Handle the three cases separately, in the hope of getting
174	 * better/faster code.
175	 */
176	switch (base) {
177	case 10:
178		if (val < 10) {	/* many numbers are 1 digit */
179			*--cp = to_char(val);
180			return (cp);
181		}
182		/*
183		 * On many machines, unsigned arithmetic is harder than
184		 * signed arithmetic, so we do at most one unsigned mod and
185		 * divide; this is sufficient to reduce the range of
186		 * the incoming value to where signed arithmetic works.
187		 */
188		if (val > LONG_MAX) {
189			*--cp = to_char(val % 10);
190			sval = val / 10;
191		} else
192			sval = val;
193		do {
194			*--cp = to_char(sval % 10);
195			sval /= 10;
196		} while (sval != 0);
197		break;
198
199	case 8:
200		do {
201			*--cp = to_char(val & 7);
202			val >>= 3;
203		} while (val);
204		if (octzero && *cp != '0')
205			*--cp = '0';
206		break;
207
208	case 16:
209		do {
210			*--cp = xdigs[val & 15];
211			val >>= 4;
212		} while (val);
213		break;
214
215	default:			/* oops */
216		abort();
217	}
218	return (cp);
219}
220
221/* Identical to __ultoa, but for intmax_t. */
222static CHAR *
223__ujtoa(uintmax_t val, CHAR *endp, int base, int octzero, const char *xdigs)
224{
225	CHAR *cp = endp;
226	intmax_t sval;
227
228	/* quick test for small values; __ultoa is typically much faster */
229	/* (perhaps instead we should run until small, then call __ultoa?) */
230	if (val <= ULONG_MAX)
231		return (__ultoa((u_long)val, endp, base, octzero, xdigs));
232	switch (base) {
233	case 10:
234		if (val < 10) {
235			*--cp = to_char(val % 10);
236			return (cp);
237		}
238		if (val > INTMAX_MAX) {
239			*--cp = to_char(val % 10);
240			sval = val / 10;
241		} else
242			sval = val;
243		do {
244			*--cp = to_char(sval % 10);
245			sval /= 10;
246		} while (sval != 0);
247		break;
248
249	case 8:
250		do {
251			*--cp = to_char(val & 7);
252			val >>= 3;
253		} while (val);
254		if (octzero && *cp != '0')
255			*--cp = '0';
256		break;
257
258	case 16:
259		do {
260			*--cp = xdigs[val & 15];
261			val >>= 4;
262		} while (val);
263		break;
264
265	default:
266		abort();
267	}
268	return (cp);
269}
270
271#ifndef NO_FLOATING_POINT
272
273static int
274exponent(CHAR *p0, int exp, CHAR fmtch)
275{
276	CHAR *p, *t;
277	CHAR expbuf[MAXEXPDIG];
278
279	p = p0;
280	*p++ = fmtch;
281	if (exp < 0) {
282		exp = -exp;
283		*p++ = '-';
284	}
285	else
286		*p++ = '+';
287	t = expbuf + MAXEXPDIG;
288	if (exp > 9) {
289		do {
290			*--t = to_char(exp % 10);
291		} while ((exp /= 10) > 9);
292		*--t = to_char(exp);
293		for (; t < expbuf + MAXEXPDIG; *p++ = *t++);
294	}
295	else {
296		/*
297		 * Exponents for decimal floating point conversions
298		 * (%[eEgG]) must be at least two characters long,
299		 * whereas exponents for hexadecimal conversions can
300		 * be only one character long.
301		 */
302		if (fmtch == 'e' || fmtch == 'E')
303			*p++ = '0';
304		*p++ = to_char(exp);
305	}
306	return (p - p0);
307}
308
309#endif /* !NO_FLOATING_POINT */
310