Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/modules/Libc/stdio/printfcommon.h

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

Archive Download this file

Revision: 2182