Line data Source code
1 : /*-
2 : * SPDX-License-Identifier: BSD-3-Clause
3 : *
4 : * Copyright (c) 1990, 1993
5 : * The Regents of the University of California. All rights reserved.
6 : *
7 : * This code is derived from software contributed to Berkeley by
8 : * Chris Torek.
9 : *
10 : * Copyright (c) 2011 The FreeBSD Foundation
11 : * All rights reserved.
12 : * Portions of this software were developed by David Chisnall
13 : * under sponsorship from the FreeBSD Foundation.
14 : *
15 : * Redistribution and use in source and binary forms, with or without
16 : * modification, are permitted provided that the following conditions
17 : * are met:
18 : * 1. Redistributions of source code must retain the above copyright
19 : * notice, this list of conditions and the following disclaimer.
20 : * 2. Redistributions in binary form must reproduce the above copyright
21 : * notice, this list of conditions and the following disclaimer in the
22 : * documentation and/or other materials provided with the distribution.
23 : * 3. Neither the name of the University nor the names of its contributors
24 : * may be used to endorse or promote products derived from this software
25 : * without specific prior written permission.
26 : *
27 : * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 : * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 : * SUCH DAMAGE.
38 : *
39 : * $FreeBSD$
40 : */
41 :
42 : /*
43 : * This file defines common routines used by both printf and wprintf.
44 : * You must define CHAR to either char or wchar_t prior to including this.
45 : */
46 :
47 :
48 : static CHAR *__ujtoa(uintmax_t, CHAR *, int, int, const char *);
49 : static CHAR *__ultoa(u_long, CHAR *, int, int, const char *);
50 :
51 : #define NIOV 8
52 : struct io_state {
53 : struct fbuf *cb;
54 : size_t avail;
55 : };
56 :
57 : static inline void
58 1250 : io_init(struct io_state *iop, struct fbuf *cb)
59 : {
60 1250 : iop->cb = cb;
61 1250 : iop->avail = cb ? cb->len - (cb->pos - cb->buf) : 0;
62 : }
63 :
64 : /*
65 : * WARNING: The buffer passed to io_print() is not copied immediately; it must
66 : * remain valid until io_flush() is called.
67 : */
68 : static inline int
69 5435 : io_print(struct io_state *iop, const CHAR * __restrict ptr, size_t len)
70 : {
71 5435 : size_t copylen = len;
72 :
73 5435 : if (!iop->cb)
74 : return 0;
75 5435 : if (iop->avail < copylen)
76 : copylen = iop->avail;
77 :
78 5435 : memcpy(iop->cb->pos, ptr, copylen);
79 5435 : iop->avail -= copylen;
80 5435 : iop->cb->pos += copylen;
81 5435 : return 0;
82 : }
83 :
84 : /*
85 : * Choose PADSIZE to trade efficiency vs. size. If larger printf
86 : * fields occur frequently, increase PADSIZE and make the initialisers
87 : * below longer.
88 : */
89 : #define PADSIZE 16 /* pad chunk size */
90 : static const CHAR blanks[PADSIZE] =
91 : {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
92 : static const CHAR zeroes[PADSIZE] =
93 : {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
94 :
95 : /*
96 : * Pad with blanks or zeroes. 'with' should point to either the blanks array
97 : * or the zeroes array.
98 : */
99 : static inline int
100 4744 : io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with)
101 : {
102 4744 : int n;
103 :
104 5480 : while (howmany > 0) {
105 736 : n = (howmany >= PADSIZE) ? PADSIZE : howmany;
106 736 : if (io_print(iop, with, n))
107 : return (-1);
108 736 : howmany -= n;
109 : }
110 : return (0);
111 : }
112 :
113 : /*
114 : * Print exactly len characters of the string spanning p to ep, truncating
115 : * or padding with 'with' as necessary.
116 : */
117 : static inline int
118 : io_printandpad(struct io_state *iop, const CHAR *p, const CHAR *ep,
119 : int len, const CHAR * __restrict with)
120 : {
121 : int p_len;
122 :
123 : p_len = ep - p;
124 : if (p_len > len)
125 : p_len = len;
126 : if (p_len > 0) {
127 : if (io_print(iop, p, p_len))
128 : return (-1);
129 : } else {
130 : p_len = 0;
131 : }
132 : return (io_pad(iop, len - p_len, with));
133 : }
134 :
135 : /*
136 : * Convert an unsigned long to ASCII for printf purposes, returning
137 : * a pointer to the first character of the string representation.
138 : * Octal numbers can be forced to have a leading zero; hex numbers
139 : * use the given digits.
140 : */
141 : static CHAR *
142 1234 : __ultoa(u_long val, CHAR *endp, int base, int octzero, const char *xdigs)
143 : {
144 1234 : CHAR *cp = endp;
145 1234 : long sval;
146 :
147 : /*
148 : * Handle the three cases separately, in the hope of getting
149 : * better/faster code.
150 : */
151 1234 : switch (base) {
152 1234 : case 10:
153 1234 : if (val < 10) { /* many numbers are 1 digit */
154 760 : *--cp = to_char(val);
155 760 : return (cp);
156 : }
157 : /*
158 : * On many machines, unsigned arithmetic is harder than
159 : * signed arithmetic, so we do at most one unsigned mod and
160 : * divide; this is sufficient to reduce the range of
161 : * the incoming value to where signed arithmetic works.
162 : */
163 474 : if (val > LONG_MAX) {
164 0 : *--cp = to_char(val % 10);
165 0 : sval = val / 10;
166 : } else
167 : sval = val;
168 3384 : do {
169 3384 : *--cp = to_char(sval % 10);
170 3384 : sval /= 10;
171 3384 : } while (sval != 0);
172 : break;
173 :
174 0 : case 8:
175 0 : do {
176 0 : *--cp = to_char(val & 7);
177 0 : val >>= 3;
178 0 : } while (val);
179 0 : if (octzero && *cp != '0')
180 0 : *--cp = '0';
181 : break;
182 :
183 0 : case 16:
184 0 : do {
185 0 : *--cp = xdigs[val & 15];
186 0 : val >>= 4;
187 0 : } while (val);
188 : break;
189 :
190 0 : default: /* oops */
191 0 : abort();
192 : }
193 : return (cp);
194 : }
195 :
196 : /* Identical to __ultoa, but for intmax_t. */
197 : static CHAR *
198 111 : __ujtoa(uintmax_t val, CHAR *endp, int base, int octzero, const char *xdigs)
199 : {
200 111 : CHAR *cp = endp;
201 111 : intmax_t sval;
202 :
203 : /* quick test for small values; __ultoa is typically much faster */
204 : /* (perhaps instead we should run until small, then call __ultoa?) */
205 111 : if (val <= ULONG_MAX)
206 111 : return (__ultoa((u_long)val, endp, base, octzero, xdigs));
207 : switch (base) {
208 : case 10:
209 : if (val < 10) {
210 : *--cp = to_char(val % 10);
211 : return (cp);
212 : }
213 : if (val > INTMAX_MAX) {
214 : *--cp = to_char(val % 10);
215 : sval = val / 10;
216 : } else
217 : sval = val;
218 : do {
219 : *--cp = to_char(sval % 10);
220 : sval /= 10;
221 : } while (sval != 0);
222 : break;
223 :
224 : case 8:
225 : do {
226 : *--cp = to_char(val & 7);
227 : val >>= 3;
228 : } while (val);
229 : if (octzero && *cp != '0')
230 : *--cp = '0';
231 : break;
232 :
233 : case 16:
234 : do {
235 : *--cp = xdigs[val & 15];
236 : val >>= 4;
237 : } while (val);
238 : break;
239 :
240 : default:
241 : abort();
242 : }
243 : return (cp);
244 : }
|