]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libc/stdio/printfcommon.h
Reduce code duplication by moving functions that are identical in both
[FreeBSD/FreeBSD.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 *, int, char,
58                     const char *);
59 static CHAR     *__ultoa(u_long, CHAR *, int, int, const char *, int, char,
60                     const char *);
61
62 #define NIOV 8
63 struct io_state {
64         FILE *fp;
65         struct __suio uio;      /* output information: summary */
66         struct __siov iov[NIOV];/* ... and individual io vectors */
67         struct __siov *iovp;    /* pointer to next free slot in iov */
68 };
69
70 static inline void
71 io_init(struct io_state *iop, FILE *fp)
72 {
73
74         iop->uio.uio_iov = iop->iovp = iop->iov;
75         iop->uio.uio_resid = 0;
76         iop->uio.uio_iovcnt = 0;
77         iop->fp = fp;
78 }
79
80 /*
81  * WARNING: The buffer passed to io_print() is not copied immediately; it must
82  * remain valid until io_flush() is called.
83  */
84 static inline int
85 io_print(struct io_state *iop, const CHAR * __restrict ptr, int len)
86 {
87
88         iop->iovp->iov_base = (char *)ptr;
89         iop->iovp->iov_len = len;
90         iop->uio.uio_resid += len;
91         iop->iovp++;
92         if (++iop->uio.uio_iovcnt >= NIOV) {
93                 iop->iovp = iop->iov;
94                 return (__sprint(iop->fp, &iop->uio));
95         }
96         return (0);
97 }
98
99 /*
100  * Choose PADSIZE to trade efficiency vs. size.  If larger printf
101  * fields occur frequently, increase PADSIZE and make the initialisers
102  * below longer.
103  */
104 #define PADSIZE 16              /* pad chunk size */
105 static const CHAR blanks[PADSIZE] =
106 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
107 static const CHAR zeroes[PADSIZE] =
108 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
109
110 /*
111  * Pad with blanks or zeroes. 'with' should point to either the blanks array
112  * or the zeroes array.
113  */
114 static inline int
115 io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with)
116 {
117
118         while (howmany > PADSIZE) {
119                 if (io_print(iop, with, PADSIZE))
120                         return (-1);
121                 howmany -= PADSIZE;
122         }
123         if (howmany > 0 && io_print(iop, with, howmany))
124                 return (-1);
125         return (0);
126 }
127
128 /*
129  * Print exactly len characters of the string spanning p to ep, truncating
130  * or padding with 'with' as necessary.
131  */
132 static inline int
133 io_printandpad(struct io_state *iop, const CHAR *p, const CHAR *ep,
134                int len, const CHAR * __restrict with)
135 {
136         int p_len;
137
138         p_len = ep - p;
139         if (p_len > len)
140                 p_len = len;
141         if (p_len > 0 && io_print(iop, p, p_len))
142                 return (-1);
143         return (io_pad(iop, len - (p_len > 0 ? p_len : 0), with));
144 }
145
146 static inline int
147 io_flush(struct io_state *iop)
148 {
149
150         iop->iovp = iop->iov;
151         return (__sprint(iop->fp, &iop->uio));
152 }
153
154 /*
155  * Convert an unsigned long to ASCII for printf purposes, returning
156  * a pointer to the first character of the string representation.
157  * Octal numbers can be forced to have a leading zero; hex numbers
158  * use the given digits.
159  */
160 static CHAR *
161 __ultoa(u_long val, CHAR *endp, int base, int octzero, const char *xdigs,
162         int needgrp, char thousep, const char *grp)
163 {
164         CHAR *cp = endp;
165         long sval;
166         int ndig;
167
168         /*
169          * Handle the three cases separately, in the hope of getting
170          * better/faster code.
171          */
172         switch (base) {
173         case 10:
174                 if (val < 10) { /* many numbers are 1 digit */
175                         *--cp = to_char(val);
176                         return (cp);
177                 }
178                 ndig = 0;
179                 /*
180                  * On many machines, unsigned arithmetic is harder than
181                  * signed arithmetic, so we do at most one unsigned mod and
182                  * divide; this is sufficient to reduce the range of
183                  * the incoming value to where signed arithmetic works.
184                  */
185                 if (val > LONG_MAX) {
186                         *--cp = to_char(val % 10);
187                         ndig++;
188                         sval = val / 10;
189                 } else
190                         sval = val;
191                 do {
192                         *--cp = to_char(sval % 10);
193                         ndig++;
194                         /*
195                          * If (*grp == CHAR_MAX) then no more grouping
196                          * should be performed.
197                          */
198                         if (needgrp && ndig == *grp && *grp != CHAR_MAX
199                                         && sval > 9) {
200                                 *--cp = thousep;
201                                 ndig = 0;
202                                 /*
203                                  * If (*(grp+1) == '\0') then we have to
204                                  * use *grp character (last grouping rule)
205                                  * for all next cases
206                                  */
207                                 if (*(grp+1) != '\0')
208                                         grp++;
209                         }
210                         sval /= 10;
211                 } while (sval != 0);
212                 break;
213
214         case 8:
215                 do {
216                         *--cp = to_char(val & 7);
217                         val >>= 3;
218                 } while (val);
219                 if (octzero && *cp != '0')
220                         *--cp = '0';
221                 break;
222
223         case 16:
224                 do {
225                         *--cp = xdigs[val & 15];
226                         val >>= 4;
227                 } while (val);
228                 break;
229
230         default:                        /* oops */
231                 abort();
232         }
233         return (cp);
234 }
235
236 /* Identical to __ultoa, but for intmax_t. */
237 static CHAR *
238 __ujtoa(uintmax_t val, CHAR *endp, int base, int octzero, const char *xdigs,
239         int needgrp, char thousep, const char *grp)
240 {
241         CHAR *cp = endp;
242         intmax_t sval;
243         int ndig;
244
245         /* quick test for small values; __ultoa is typically much faster */
246         /* (perhaps instead we should run until small, then call __ultoa?) */
247         if (val <= ULONG_MAX)
248                 return (__ultoa((u_long)val, endp, base, octzero, xdigs,
249                     needgrp, thousep, grp));
250         switch (base) {
251         case 10:
252                 if (val < 10) {
253                         *--cp = to_char(val % 10);
254                         return (cp);
255                 }
256                 ndig = 0;
257                 if (val > INTMAX_MAX) {
258                         *--cp = to_char(val % 10);
259                         ndig++;
260                         sval = val / 10;
261                 } else
262                         sval = val;
263                 do {
264                         *--cp = to_char(sval % 10);
265                         ndig++;
266                         /*
267                          * If (*grp == CHAR_MAX) then no more grouping
268                          * should be performed.
269                          */
270                         if (needgrp && *grp != CHAR_MAX && ndig == *grp
271                                         && sval > 9) {
272                                 *--cp = thousep;
273                                 ndig = 0;
274                                 /*
275                                  * If (*(grp+1) == '\0') then we have to
276                                  * use *grp character (last grouping rule)
277                                  * for all next cases
278                                  */
279                                 if (*(grp+1) != '\0')
280                                         grp++;
281                         }
282                         sval /= 10;
283                 } while (sval != 0);
284                 break;
285
286         case 8:
287                 do {
288                         *--cp = to_char(val & 7);
289                         val >>= 3;
290                 } while (val);
291                 if (octzero && *cp != '0')
292                         *--cp = '0';
293                 break;
294
295         case 16:
296                 do {
297                         *--cp = xdigs[val & 15];
298                         val >>= 4;
299                 } while (val);
300                 break;
301
302         default:
303                 abort();
304         }
305         return (cp);
306 }
307
308 #ifndef NO_FLOATING_POINT
309
310 static int
311 exponent(CHAR *p0, int exp, CHAR fmtch)
312 {
313         CHAR *p, *t;
314         CHAR expbuf[MAXEXPDIG];
315
316         p = p0;
317         *p++ = fmtch;
318         if (exp < 0) {
319                 exp = -exp;
320                 *p++ = '-';
321         }
322         else
323                 *p++ = '+';
324         t = expbuf + MAXEXPDIG;
325         if (exp > 9) {
326                 do {
327                         *--t = to_char(exp % 10);
328                 } while ((exp /= 10) > 9);
329                 *--t = to_char(exp);
330                 for (; t < expbuf + MAXEXPDIG; *p++ = *t++);
331         }
332         else {
333                 /*
334                  * Exponents for decimal floating point conversions
335                  * (%[eEgG]) must be at least two characters long,
336                  * whereas exponents for hexadecimal conversions can
337                  * be only one character long.
338                  */
339                 if (fmtch == 'e' || fmtch == 'E')
340                         *p++ = '0';
341                 *p++ = to_char(exp);
342         }
343         return (p - p0);
344 }
345
346 #endif /* !NO_FLOATING_POINT */