]>
Commit | Line | Data |
---|---|---|
1f2f436a A |
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 2009/01/22 08:14:28 das 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 | #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 | |
ad3c9f2a | 82 | io_print(struct io_state *iop, const CHAR * __restrict ptr, int len, locale_t loc) |
1f2f436a A |
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) | |
ad3c9f2a | 89 | return (__sprint(iop->fp, loc, &iop->uio)); |
1f2f436a A |
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 | |
ad3c9f2a | 110 | io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with, locale_t loc) |
1f2f436a A |
111 | { |
112 | int n; | |
113 | ||
114 | while (howmany > 0) { | |
115 | n = (howmany >= PADSIZE) ? PADSIZE : howmany; | |
ad3c9f2a | 116 | if (io_print(iop, with, n, loc)) |
1f2f436a A |
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, | |
ad3c9f2a | 129 | int len, const CHAR * __restrict with, locale_t loc) |
1f2f436a A |
130 | { |
131 | int p_len; | |
132 | ||
23e20b00 | 133 | p_len = (int)(ep - p); |
1f2f436a A |
134 | if (p_len > len) |
135 | p_len = len; | |
136 | if (p_len > 0) { | |
ad3c9f2a | 137 | if (io_print(iop, p, p_len, loc)) |
1f2f436a A |
138 | return (-1); |
139 | } else { | |
140 | p_len = 0; | |
141 | } | |
ad3c9f2a | 142 | return (io_pad(iop, len - p_len, with, loc)); |
1f2f436a A |
143 | } |
144 | ||
145 | static inline int | |
ad3c9f2a | 146 | io_flush(struct io_state *iop, locale_t loc) |
1f2f436a A |
147 | { |
148 | ||
ad3c9f2a | 149 | return (__sprint(iop->fp, loc, &iop->uio)); |
1f2f436a A |
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 */ | |
23e20b00 | 171 | *--cp = (CHAR)to_char(val); |
1f2f436a A |
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 */ | |
ad3c9f2a | 208 | LIBC_ABORT("__ultoa: invalid base=%d", base); |
1f2f436a A |
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: | |
ad3c9f2a | 258 | LIBC_ABORT("__ujtoa: invalid base=%d", base); |
1f2f436a A |
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 | } | |
23e20b00 | 298 | return (int)(p - p0); |
1f2f436a A |
299 | } |
300 | ||
301 | #endif /* !NO_FLOATING_POINT */ |