printfcommon.h revision 187284
1187277Sdas/*-
2187277Sdas * Copyright (c) 1990, 1993
3187277Sdas *	The Regents of the University of California.  All rights reserved.
4187277Sdas *
5187277Sdas * This code is derived from software contributed to Berkeley by
6187277Sdas * Chris Torek.
7187277Sdas *
8187277Sdas * Redistribution and use in source and binary forms, with or without
9187277Sdas * modification, are permitted provided that the following conditions
10187277Sdas * are met:
11187277Sdas * 1. Redistributions of source code must retain the above copyright
12187277Sdas *    notice, this list of conditions and the following disclaimer.
13187277Sdas * 2. Redistributions in binary form must reproduce the above copyright
14187277Sdas *    notice, this list of conditions and the following disclaimer in the
15187277Sdas *    documentation and/or other materials provided with the distribution.
16187277Sdas * 4. Neither the name of the University nor the names of its contributors
17187277Sdas *    may be used to endorse or promote products derived from this software
18187277Sdas *    without specific prior written permission.
19187277Sdas *
20187277Sdas * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21187277Sdas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22187277Sdas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23187277Sdas * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24187277Sdas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25187277Sdas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26187277Sdas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27187277Sdas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28187277Sdas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29187277Sdas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30187277Sdas * SUCH DAMAGE.
31187277Sdas *
32187277Sdas * $FreeBSD: head/lib/libc/stdio/printfcommon.h 187284 2009-01-15 04:49:43Z das $
33187277Sdas */
34187277Sdas
35187277Sdas/*
36187277Sdas * This file defines common routines used by both printf and wprintf.
37187277Sdas * You must define CHAR to either char or wchar_t prior to including this.
38187277Sdas */
39187277Sdas
40187284Sdas
41187284Sdas#ifndef NO_FLOATING_POINT
42187284Sdas
43187284Sdas#define	dtoa		__dtoa
44187284Sdas#define	freedtoa	__freedtoa
45187284Sdas
46187284Sdas#include <float.h>
47187284Sdas#include <math.h>
48187284Sdas#include "floatio.h"
49187284Sdas#include "gdtoa.h"
50187284Sdas
51187284Sdas#define	DEFPREC		6
52187284Sdas
53187284Sdasstatic int exponent(CHAR *, int, CHAR);
54187284Sdas
55187284Sdas#endif /* !NO_FLOATING_POINT */
56187284Sdas
57187284Sdasstatic CHAR	*__ujtoa(uintmax_t, CHAR *, int, int, const char *, int, char,
58187284Sdas		    const char *);
59187284Sdasstatic CHAR	*__ultoa(u_long, CHAR *, int, int, const char *, int, char,
60187284Sdas		    const char *);
61187284Sdas
62187277Sdas#define NIOV 8
63187277Sdasstruct io_state {
64187277Sdas	FILE *fp;
65187277Sdas	struct __suio uio;	/* output information: summary */
66187277Sdas	struct __siov iov[NIOV];/* ... and individual io vectors */
67187277Sdas	struct __siov *iovp;	/* pointer to next free slot in iov */
68187277Sdas};
69187277Sdas
70187277Sdasstatic inline void
71187277Sdasio_init(struct io_state *iop, FILE *fp)
72187277Sdas{
73187277Sdas
74187277Sdas	iop->uio.uio_iov = iop->iovp = iop->iov;
75187277Sdas	iop->uio.uio_resid = 0;
76187277Sdas	iop->uio.uio_iovcnt = 0;
77187277Sdas	iop->fp = fp;
78187277Sdas}
79187277Sdas
80187277Sdas/*
81187277Sdas * WARNING: The buffer passed to io_print() is not copied immediately; it must
82187277Sdas * remain valid until io_flush() is called.
83187277Sdas */
84187277Sdasstatic inline int
85187277Sdasio_print(struct io_state *iop, const CHAR * __restrict ptr, int len)
86187277Sdas{
87187277Sdas
88187277Sdas	iop->iovp->iov_base = (char *)ptr;
89187277Sdas	iop->iovp->iov_len = len;
90187277Sdas	iop->uio.uio_resid += len;
91187277Sdas	iop->iovp++;
92187277Sdas	if (++iop->uio.uio_iovcnt >= NIOV) {
93187277Sdas		iop->iovp = iop->iov;
94187277Sdas		return (__sprint(iop->fp, &iop->uio));
95187277Sdas	}
96187277Sdas	return (0);
97187277Sdas}
98187277Sdas
99187277Sdas/*
100187277Sdas * Choose PADSIZE to trade efficiency vs. size.  If larger printf
101187277Sdas * fields occur frequently, increase PADSIZE and make the initialisers
102187277Sdas * below longer.
103187277Sdas */
104187277Sdas#define	PADSIZE	16		/* pad chunk size */
105187277Sdasstatic const CHAR blanks[PADSIZE] =
106187277Sdas{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
107187277Sdasstatic const CHAR zeroes[PADSIZE] =
108187277Sdas{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
109187277Sdas
110187277Sdas/*
111187277Sdas * Pad with blanks or zeroes. 'with' should point to either the blanks array
112187277Sdas * or the zeroes array.
113187277Sdas */
114187277Sdasstatic inline int
115187277Sdasio_pad(struct io_state *iop, int howmany, const CHAR * __restrict with)
116187277Sdas{
117187277Sdas
118187277Sdas	while (howmany > PADSIZE) {
119187277Sdas		if (io_print(iop, with, PADSIZE))
120187277Sdas			return (-1);
121187277Sdas		howmany -= PADSIZE;
122187277Sdas	}
123187277Sdas	if (howmany > 0 && io_print(iop, with, howmany))
124187277Sdas		return (-1);
125187277Sdas	return (0);
126187277Sdas}
127187277Sdas
128187277Sdas/*
129187277Sdas * Print exactly len characters of the string spanning p to ep, truncating
130187277Sdas * or padding with 'with' as necessary.
131187277Sdas */
132187277Sdasstatic inline int
133187277Sdasio_printandpad(struct io_state *iop, const CHAR *p, const CHAR *ep,
134187277Sdas	       int len, const CHAR * __restrict with)
135187277Sdas{
136187277Sdas	int p_len;
137187277Sdas
138187277Sdas	p_len = ep - p;
139187277Sdas	if (p_len > len)
140187277Sdas		p_len = len;
141187277Sdas	if (p_len > 0 && io_print(iop, p, p_len))
142187277Sdas		return (-1);
143187277Sdas	return (io_pad(iop, len - (p_len > 0 ? p_len : 0), with));
144187277Sdas}
145187277Sdas
146187277Sdasstatic inline int
147187277Sdasio_flush(struct io_state *iop)
148187277Sdas{
149187277Sdas
150187277Sdas	iop->iovp = iop->iov;
151187277Sdas	return (__sprint(iop->fp, &iop->uio));
152187277Sdas}
153187284Sdas
154187284Sdas/*
155187284Sdas * Convert an unsigned long to ASCII for printf purposes, returning
156187284Sdas * a pointer to the first character of the string representation.
157187284Sdas * Octal numbers can be forced to have a leading zero; hex numbers
158187284Sdas * use the given digits.
159187284Sdas */
160187284Sdasstatic CHAR *
161187284Sdas__ultoa(u_long val, CHAR *endp, int base, int octzero, const char *xdigs,
162187284Sdas	int needgrp, char thousep, const char *grp)
163187284Sdas{
164187284Sdas	CHAR *cp = endp;
165187284Sdas	long sval;
166187284Sdas	int ndig;
167187284Sdas
168187284Sdas	/*
169187284Sdas	 * Handle the three cases separately, in the hope of getting
170187284Sdas	 * better/faster code.
171187284Sdas	 */
172187284Sdas	switch (base) {
173187284Sdas	case 10:
174187284Sdas		if (val < 10) {	/* many numbers are 1 digit */
175187284Sdas			*--cp = to_char(val);
176187284Sdas			return (cp);
177187284Sdas		}
178187284Sdas		ndig = 0;
179187284Sdas		/*
180187284Sdas		 * On many machines, unsigned arithmetic is harder than
181187284Sdas		 * signed arithmetic, so we do at most one unsigned mod and
182187284Sdas		 * divide; this is sufficient to reduce the range of
183187284Sdas		 * the incoming value to where signed arithmetic works.
184187284Sdas		 */
185187284Sdas		if (val > LONG_MAX) {
186187284Sdas			*--cp = to_char(val % 10);
187187284Sdas			ndig++;
188187284Sdas			sval = val / 10;
189187284Sdas		} else
190187284Sdas			sval = val;
191187284Sdas		do {
192187284Sdas			*--cp = to_char(sval % 10);
193187284Sdas			ndig++;
194187284Sdas			/*
195187284Sdas			 * If (*grp == CHAR_MAX) then no more grouping
196187284Sdas			 * should be performed.
197187284Sdas			 */
198187284Sdas			if (needgrp && ndig == *grp && *grp != CHAR_MAX
199187284Sdas					&& sval > 9) {
200187284Sdas				*--cp = thousep;
201187284Sdas				ndig = 0;
202187284Sdas				/*
203187284Sdas				 * If (*(grp+1) == '\0') then we have to
204187284Sdas				 * use *grp character (last grouping rule)
205187284Sdas				 * for all next cases
206187284Sdas				 */
207187284Sdas				if (*(grp+1) != '\0')
208187284Sdas					grp++;
209187284Sdas			}
210187284Sdas			sval /= 10;
211187284Sdas		} while (sval != 0);
212187284Sdas		break;
213187284Sdas
214187284Sdas	case 8:
215187284Sdas		do {
216187284Sdas			*--cp = to_char(val & 7);
217187284Sdas			val >>= 3;
218187284Sdas		} while (val);
219187284Sdas		if (octzero && *cp != '0')
220187284Sdas			*--cp = '0';
221187284Sdas		break;
222187284Sdas
223187284Sdas	case 16:
224187284Sdas		do {
225187284Sdas			*--cp = xdigs[val & 15];
226187284Sdas			val >>= 4;
227187284Sdas		} while (val);
228187284Sdas		break;
229187284Sdas
230187284Sdas	default:			/* oops */
231187284Sdas		abort();
232187284Sdas	}
233187284Sdas	return (cp);
234187284Sdas}
235187284Sdas
236187284Sdas/* Identical to __ultoa, but for intmax_t. */
237187284Sdasstatic CHAR *
238187284Sdas__ujtoa(uintmax_t val, CHAR *endp, int base, int octzero, const char *xdigs,
239187284Sdas	int needgrp, char thousep, const char *grp)
240187284Sdas{
241187284Sdas	CHAR *cp = endp;
242187284Sdas	intmax_t sval;
243187284Sdas	int ndig;
244187284Sdas
245187284Sdas	/* quick test for small values; __ultoa is typically much faster */
246187284Sdas	/* (perhaps instead we should run until small, then call __ultoa?) */
247187284Sdas	if (val <= ULONG_MAX)
248187284Sdas		return (__ultoa((u_long)val, endp, base, octzero, xdigs,
249187284Sdas		    needgrp, thousep, grp));
250187284Sdas	switch (base) {
251187284Sdas	case 10:
252187284Sdas		if (val < 10) {
253187284Sdas			*--cp = to_char(val % 10);
254187284Sdas			return (cp);
255187284Sdas		}
256187284Sdas		ndig = 0;
257187284Sdas		if (val > INTMAX_MAX) {
258187284Sdas			*--cp = to_char(val % 10);
259187284Sdas			ndig++;
260187284Sdas			sval = val / 10;
261187284Sdas		} else
262187284Sdas			sval = val;
263187284Sdas		do {
264187284Sdas			*--cp = to_char(sval % 10);
265187284Sdas			ndig++;
266187284Sdas			/*
267187284Sdas			 * If (*grp == CHAR_MAX) then no more grouping
268187284Sdas			 * should be performed.
269187284Sdas			 */
270187284Sdas			if (needgrp && *grp != CHAR_MAX && ndig == *grp
271187284Sdas					&& sval > 9) {
272187284Sdas				*--cp = thousep;
273187284Sdas				ndig = 0;
274187284Sdas				/*
275187284Sdas				 * If (*(grp+1) == '\0') then we have to
276187284Sdas				 * use *grp character (last grouping rule)
277187284Sdas				 * for all next cases
278187284Sdas				 */
279187284Sdas				if (*(grp+1) != '\0')
280187284Sdas					grp++;
281187284Sdas			}
282187284Sdas			sval /= 10;
283187284Sdas		} while (sval != 0);
284187284Sdas		break;
285187284Sdas
286187284Sdas	case 8:
287187284Sdas		do {
288187284Sdas			*--cp = to_char(val & 7);
289187284Sdas			val >>= 3;
290187284Sdas		} while (val);
291187284Sdas		if (octzero && *cp != '0')
292187284Sdas			*--cp = '0';
293187284Sdas		break;
294187284Sdas
295187284Sdas	case 16:
296187284Sdas		do {
297187284Sdas			*--cp = xdigs[val & 15];
298187284Sdas			val >>= 4;
299187284Sdas		} while (val);
300187284Sdas		break;
301187284Sdas
302187284Sdas	default:
303187284Sdas		abort();
304187284Sdas	}
305187284Sdas	return (cp);
306187284Sdas}
307187284Sdas
308187284Sdas#ifndef NO_FLOATING_POINT
309187284Sdas
310187284Sdasstatic int
311187284Sdasexponent(CHAR *p0, int exp, CHAR fmtch)
312187284Sdas{
313187284Sdas	CHAR *p, *t;
314187284Sdas	CHAR expbuf[MAXEXPDIG];
315187284Sdas
316187284Sdas	p = p0;
317187284Sdas	*p++ = fmtch;
318187284Sdas	if (exp < 0) {
319187284Sdas		exp = -exp;
320187284Sdas		*p++ = '-';
321187284Sdas	}
322187284Sdas	else
323187284Sdas		*p++ = '+';
324187284Sdas	t = expbuf + MAXEXPDIG;
325187284Sdas	if (exp > 9) {
326187284Sdas		do {
327187284Sdas			*--t = to_char(exp % 10);
328187284Sdas		} while ((exp /= 10) > 9);
329187284Sdas		*--t = to_char(exp);
330187284Sdas		for (; t < expbuf + MAXEXPDIG; *p++ = *t++);
331187284Sdas	}
332187284Sdas	else {
333187284Sdas		/*
334187284Sdas		 * Exponents for decimal floating point conversions
335187284Sdas		 * (%[eEgG]) must be at least two characters long,
336187284Sdas		 * whereas exponents for hexadecimal conversions can
337187284Sdas		 * be only one character long.
338187284Sdas		 */
339187284Sdas		if (fmtch == 'e' || fmtch == 'E')
340187284Sdas			*p++ = '0';
341187284Sdas		*p++ = to_char(exp);
342187284Sdas	}
343187284Sdas	return (p - p0);
344187284Sdas}
345187284Sdas
346187284Sdas#endif /* !NO_FLOATING_POINT */
347