]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - lib/libc/stdio/printfcommon.h
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / lib / 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$
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 #define dtoa            __dtoa
44 #define freedtoa        __freedtoa
45
46 #include <float.h>
47 #include <math.h>
48 #include "floatio.h"
49 #include "gdtoa.h"
50
51 #define DEFPREC         6
52
53 static int exponent(CHAR *, int, CHAR);
54
55 #endif /* !NO_FLOATING_POINT */
56
57 static CHAR     *__ujtoa(uintmax_t, CHAR *, int, int, const char *);
58 static CHAR     *__ultoa(u_long, CHAR *, int, int, const char *);
59
60 #define NIOV 8
61 struct io_state {
62         FILE *fp;
63         struct __suio uio;      /* output information: summary */
64         struct __siov iov[NIOV];/* ... and individual io vectors */
65 };
66
67 static inline void
68 io_init(struct io_state *iop, FILE *fp)
69 {
70
71         iop->uio.uio_iov = iop->iov;
72         iop->uio.uio_resid = 0;
73         iop->uio.uio_iovcnt = 0;
74         iop->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  */
81 static inline int
82 io_print(struct io_state *iop, const CHAR * __restrict ptr, int len)
83 {
84
85         iop->iov[iop->uio.uio_iovcnt].iov_base = (char *)ptr;
86         iop->iov[iop->uio.uio_iovcnt].iov_len = len;
87         iop->uio.uio_resid += len;
88         if (++iop->uio.uio_iovcnt >= NIOV)
89                 return (__sprint(iop->fp, &iop->uio));
90         else
91                 return (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 #define PADSIZE 16              /* pad chunk size */
100 static const CHAR blanks[PADSIZE] =
101 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
102 static 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  */
109 static inline int
110 io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with)
111 {
112         int n;
113
114         while (howmany > 0) {
115                 n = (howmany >= PADSIZE) ? PADSIZE : howmany;
116                 if (io_print(iop, with, n))
117                         return (-1);
118                 howmany -= n;
119         }
120         return (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  */
127 static inline int
128 io_printandpad(struct io_state *iop, const CHAR *p, const CHAR *ep,
129                int len, const CHAR * __restrict with)
130 {
131         int p_len;
132
133         p_len = ep - p;
134         if (p_len > len)
135                 p_len = len;
136         if (p_len > 0) {
137                 if (io_print(iop, p, p_len))
138                         return (-1);
139         } else {
140                 p_len = 0;
141         }
142         return (io_pad(iop, len - p_len, with));
143 }
144
145 static inline int
146 io_flush(struct io_state *iop)
147 {
148
149         return (__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  */
158 static CHAR *
159 __ultoa(u_long val, CHAR *endp, int base, int octzero, const char *xdigs)
160 {
161         CHAR *cp = endp;
162         long sval;
163
164         /*
165          * Handle the three cases separately, in the hope of getting
166          * better/faster code.
167          */
168         switch (base) {
169         case 10:
170                 if (val < 10) { /* many numbers are 1 digit */
171                         *--cp = to_char(val);
172                         return (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                  */
180                 if (val > LONG_MAX) {
181                         *--cp = to_char(val % 10);
182                         sval = val / 10;
183                 } else
184                         sval = val;
185                 do {
186                         *--cp = to_char(sval % 10);
187                         sval /= 10;
188                 } while (sval != 0);
189                 break;
190
191         case 8:
192                 do {
193                         *--cp = to_char(val & 7);
194                         val >>= 3;
195                 } while (val);
196                 if (octzero && *cp != '0')
197                         *--cp = '0';
198                 break;
199
200         case 16:
201                 do {
202                         *--cp = xdigs[val & 15];
203                         val >>= 4;
204                 } while (val);
205                 break;
206
207         default:                        /* oops */
208                 abort();
209         }
210         return (cp);
211 }
212
213 /* Identical to __ultoa, but for intmax_t. */
214 static CHAR *
215 __ujtoa(uintmax_t val, CHAR *endp, int base, int octzero, const char *xdigs)
216 {
217         CHAR *cp = endp;
218         intmax_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?) */
222         if (val <= ULONG_MAX)
223                 return (__ultoa((u_long)val, endp, base, octzero, xdigs));
224         switch (base) {
225         case 10:
226                 if (val < 10) {
227                         *--cp = to_char(val % 10);
228                         return (cp);
229                 }
230                 if (val > INTMAX_MAX) {
231                         *--cp = to_char(val % 10);
232                         sval = val / 10;
233                 } else
234                         sval = val;
235                 do {
236                         *--cp = to_char(sval % 10);
237                         sval /= 10;
238                 } while (sval != 0);
239                 break;
240
241         case 8:
242                 do {
243                         *--cp = to_char(val & 7);
244                         val >>= 3;
245                 } while (val);
246                 if (octzero && *cp != '0')
247                         *--cp = '0';
248                 break;
249
250         case 16:
251                 do {
252                         *--cp = xdigs[val & 15];
253                         val >>= 4;
254                 } while (val);
255                 break;
256
257         default:
258                 abort();
259         }
260         return (cp);
261 }
262
263 #ifndef NO_FLOATING_POINT
264
265 static int
266 exponent(CHAR *p0, int exp, CHAR fmtch)
267 {
268         CHAR *p, *t;
269         CHAR expbuf[MAXEXPDIG];
270
271         p = p0;
272         *p++ = fmtch;
273         if (exp < 0) {
274                 exp = -exp;
275                 *p++ = '-';
276         }
277         else
278                 *p++ = '+';
279         t = expbuf + MAXEXPDIG;
280         if (exp > 9) {
281                 do {
282                         *--t = to_char(exp % 10);
283                 } while ((exp /= 10) > 9);
284                 *--t = to_char(exp);
285                 for (; t < expbuf + MAXEXPDIG; *p++ = *t++);
286         }
287         else {
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                  */
294                 if (fmtch == 'e' || fmtch == 'E')
295                         *p++ = '0';
296                 *p++ = to_char(exp);
297         }
298         return (p - p0);
299 }
300
301 #endif /* !NO_FLOATING_POINT */