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 | #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 */␊ |
302 | |