1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 2005 Poul-Henning Kamp
5 * Copyright (c) 1990, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Chris Torek.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * $FreeBSD$
36 */
37
38 #include <namespace.h>
39 #include <err.h>
40 #include <sys/types.h>
41 #include <stddef.h>
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <limits.h>
45 #include <locale.h>
46 #include <stdint.h>
47 #include <assert.h>
48 #include <namespace.h>
49 #include <string.h>
50 #include <wchar.h>
51 #include <un-namespace.h>
52
53 #include "printf.h"
54
55 /* private stuff -----------------------------------------------------*/
56
57 union arg {
58 int intarg;
59 u_int uintarg;
60 long longarg;
61 u_long ulongarg;
62 intmax_t intmaxarg;
63 uintmax_t uintmaxarg;
64 };
65
66 /*
67 * Macros for converting digits to letters and vice versa
68 */
69 #define to_char(n) ((n) + '0')
70
71 /* various globals ---------------------------------------------------*/
72
73 /*
74 * The size of the buffer we use for integer conversions.
75 * Technically, we would need the most space for base 10
76 * conversions with thousands' grouping characters between
77 * each pair of digits: 60 digits for 128 bit intmax_t.
78 * Use a bit more for better alignment of stuff.
79 */
80 #define BUF 64
81
82 /* misc --------------------------------------------------------------*/
83
84 /*
85 * Convert an unsigned long to ASCII for printf purposes, returning
86 * a pointer to the first character of the string representation.
87 * Octal numbers can be forced to have a leading zero; hex numbers
88 * use the given digits.
89 */
90 static char *
__ultoa(u_long val,char * endp,int base,const char * xdigs,int needgrp,char thousep,const char * grp)91 __ultoa(u_long val, char *endp, int base, const char *xdigs,
92 int needgrp, char thousep, const char *grp)
93 {
94 char *cp = endp;
95 long sval;
96 int ndig;
97
98 /*
99 * Handle the three cases separately, in the hope of getting
100 * better/faster code.
101 */
102 switch (base) {
103 case 10:
104 if (val < 10) { /* many numbers are 1 digit */
105 *--cp = to_char(val);
106 return (cp);
107 }
108 ndig = 0;
109 /*
110 * On many machines, unsigned arithmetic is harder than
111 * signed arithmetic, so we do at most one unsigned mod and
112 * divide; this is sufficient to reduce the range of
113 * the incoming value to where signed arithmetic works.
114 */
115 if (val > LONG_MAX) {
116 *--cp = to_char(val % 10);
117 ndig++;
118 sval = val / 10;
119 } else
120 sval = val;
121 do {
122 *--cp = to_char(sval % 10);
123 ndig++;
124 /*
125 * If (*grp == CHAR_MAX) then no more grouping
126 * should be performed.
127 */
128 if (needgrp && ndig == *grp && *grp != CHAR_MAX
129 && sval > 9) {
130 *--cp = thousep;
131 ndig = 0;
132 /*
133 * If (*(grp+1) == '\0') then we have to
134 * use *grp character (last grouping rule)
135 * for all next cases
136 */
137 if (*(grp+1) != '\0')
138 grp++;
139 }
140 sval /= 10;
141 } while (sval != 0);
142 break;
143
144 case 8:
145 do {
146 *--cp = to_char(val & 7);
147 val >>= 3;
148 } while (val);
149 break;
150
151 case 16:
152 do {
153 *--cp = xdigs[val & 15];
154 val >>= 4;
155 } while (val);
156 break;
157
158 default: /* oops */
159 assert(base == 16);
160 }
161 return (cp);
162 }
163
164
165 /* Identical to __ultoa, but for intmax_t. */
166 static char *
__ujtoa(uintmax_t val,char * endp,int base,const char * xdigs,int needgrp,char thousep,const char * grp)167 __ujtoa(uintmax_t val, char *endp, int base, const char *xdigs,
168 int needgrp, char thousep, const char *grp)
169 {
170 char *cp = endp;
171 intmax_t sval;
172 int ndig;
173
174 switch (base) {
175 case 10:
176 if (val < 10) {
177 *--cp = to_char(val % 10);
178 return (cp);
179 }
180 ndig = 0;
181 if (val > INTMAX_MAX) {
182 *--cp = to_char(val % 10);
183 ndig++;
184 sval = val / 10;
185 } else
186 sval = val;
187 do {
188 *--cp = to_char(sval % 10);
189 ndig++;
190 /*
191 * If (*grp == CHAR_MAX) then no more grouping
192 * should be performed.
193 */
194 if (needgrp && *grp != CHAR_MAX && ndig == *grp
195 && sval > 9) {
196 *--cp = thousep;
197 ndig = 0;
198 /*
199 * If (*(grp+1) == '\0') then we have to
200 * use *grp character (last grouping rule)
201 * for all next cases
202 */
203 if (*(grp+1) != '\0')
204 grp++;
205 }
206 sval /= 10;
207 } while (sval != 0);
208 break;
209
210 case 8:
211 do {
212 *--cp = to_char(val & 7);
213 val >>= 3;
214 } while (val);
215 break;
216
217 case 16:
218 do {
219 *--cp = xdigs[val & 15];
220 val >>= 4;
221 } while (val);
222 break;
223
224 default:
225 abort();
226 }
227 return (cp);
228 }
229
230
231 /* 'd' ---------------------------------------------------------------*/
232
233 int
__printf_arginfo_int(const struct printf_info * pi,size_t n,int * argt)234 __printf_arginfo_int(const struct printf_info *pi, size_t n, int *argt)
235 {
236 assert (n > 0);
237 argt[0] = PA_INT;
238 if (pi->is_ptrdiff)
239 argt[0] |= PA_FLAG_PTRDIFF;
240 else if (pi->is_size)
241 argt[0] |= PA_FLAG_SIZE;
242 else if (pi->is_long)
243 argt[0] |= PA_FLAG_LONG;
244 else if (pi->is_intmax)
245 argt[0] |= PA_FLAG_INTMAX;
246 else if (pi->is_quad)
247 argt[0] |= PA_FLAG_QUAD;
248 else if (pi->is_long_double)
249 argt[0] |= PA_FLAG_LONG_LONG;
250 else if (pi->is_short)
251 argt[0] |= PA_FLAG_SHORT;
252 else if (pi->is_char)
253 argt[0] = PA_CHAR;
254 return (1);
255 }
256
257 int
__printf_render_int(struct __printf_io * io,const struct printf_info * pi,const void * const * arg)258 __printf_render_int(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
259 {
260 const union arg *argp;
261 char buf[BUF];
262 char *p, *pe;
263 char ns;
264 int l, ngrp, rdx, sign, zext;
265 const char *nalt, *digit;
266 char thousands_sep; /* locale specific thousands separator */
267 const char *grouping; /* locale specific numeric grouping rules */
268 uintmax_t uu;
269 int ret;
270
271 ret = 0;
272 nalt = NULL;
273 digit = __lowercase_hex;
274 ns = '\0';
275 pe = buf + sizeof buf - 1;
276
277 if (pi->group) {
278 thousands_sep = *(localeconv()->thousands_sep);
279 grouping = localeconv()->grouping;
280 ngrp = 1;
281 } else {
282 thousands_sep = 0;
283 grouping = NULL;
284 ngrp = 0;
285 }
286
287 switch(pi->spec) {
288 case 'd':
289 case 'i':
290 rdx = 10;
291 sign = 1;
292 break;
293 case 'X':
294 digit = __uppercase_hex;
295 /*FALLTHOUGH*/
296 case 'x':
297 rdx = 16;
298 sign = 0;
299 break;
300 case 'u':
301 case 'U':
302 rdx = 10;
303 sign = 0;
304 break;
305 case 'o':
306 case 'O':
307 rdx = 8;
308 sign = 0;
309 break;
310 default:
311 fprintf(stderr, "pi->spec = '%c'\n", pi->spec);
312 assert(1 == 0);
313 }
314 argp = arg[0];
315
316 if (sign)
317 ns = pi->showsign;
318
319 if (pi->is_long_double || pi->is_quad || pi->is_intmax ||
320 pi->is_size || pi->is_ptrdiff) {
321 if (sign && argp->intmaxarg < 0) {
322 uu = -argp->intmaxarg;
323 ns = '-';
324 } else
325 uu = argp->uintmaxarg;
326 } else if (pi->is_long) {
327 if (sign && argp->longarg < 0) {
328 uu = (u_long)-argp->longarg;
329 ns = '-';
330 } else
331 uu = argp->ulongarg;
332 } else if (pi->is_short) {
333 if (sign && (short)argp->intarg < 0) {
334 uu = -(short)argp->intarg;
335 ns = '-';
336 } else
337 uu = (unsigned short)argp->uintarg;
338 } else if (pi->is_char) {
339 if (sign && (signed char)argp->intarg < 0) {
340 uu = -(signed char)argp->intarg;
341 ns = '-';
342 } else
343 uu = (unsigned char)argp->uintarg;
344 } else {
345 if (sign && argp->intarg < 0) {
346 uu = (unsigned)-argp->intarg;
347 ns = '-';
348 } else
349 uu = argp->uintarg;
350 }
351 if (uu <= ULONG_MAX)
352 p = __ultoa(uu, pe, rdx, digit, ngrp, thousands_sep, grouping);
353 else
354 p = __ujtoa(uu, pe, rdx, digit, ngrp, thousands_sep, grouping);
355
356 l = 0;
357 if (uu == 0) {
358 /*-
359 * ``The result of converting a zero value with an
360 * explicit precision of zero is no characters.''
361 * -- ANSI X3J11
362 *
363 * ``The C Standard is clear enough as is. The call
364 * printf("%#.0o", 0) should print 0.''
365 * -- Defect Report #151
366 */
367 ;
368 if (pi->prec == 0 && !(pi->alt && rdx == 8))
369 p = pe;
370 } else if (pi->alt) {
371 if (rdx == 8)
372 *--p = '0';
373 if (rdx == 16) {
374 if (pi->spec == 'x')
375 nalt = "0x";
376 else
377 nalt = "0X";
378 l += 2;
379 }
380 }
381 l += pe - p;
382 if (ns)
383 l++;
384
385 /*-
386 * ``... diouXx conversions ... if a precision is
387 * specified, the 0 flag will be ignored.''
388 * -- ANSI X3J11
389 */
390 if (pi->prec > (pe - p))
391 zext = pi->prec - (pe - p);
392 else if (pi->prec != -1)
393 zext = 0;
394 else if (pi->pad == '0' && pi->width > l && !pi->left)
395 zext = pi->width - l;
396 else
397 zext = 0;
398
399 l += zext;
400
401 while (zext > 0 && p > buf) {
402 *--p = '0';
403 zext--;
404 }
405
406 if (l < BUF) {
407 if (ns) {
408 *--p = ns;
409 } else if (nalt != NULL) {
410 *--p = nalt[1];
411 *--p = nalt[0];
412 }
413 if (pi->width > (pe - p) && !pi->left) {
414 l = pi->width - (pe - p);
415 while (l > 0 && p > buf) {
416 *--p = ' ';
417 l--;
418 }
419 if (l)
420 ret += __printf_pad(io, l, 0);
421 }
422 } else {
423 if (!pi->left && pi->width > l)
424 ret += __printf_pad(io, pi->width - l, 0);
425 if (ns != '\0')
426 ret += __printf_puts(io, &ns, 1);
427 else if (nalt != NULL)
428 ret += __printf_puts(io, nalt, 2);
429 if (zext > 0)
430 ret += __printf_pad(io, zext, 1);
431 }
432
433 ret += __printf_puts(io, p, pe - p);
434 if (pi->width > ret && pi->left)
435 ret += __printf_pad(io, pi->width - ret, 0);
436 __printf_flush(io);
437 return (ret);
438 }
439
440 /* 'p' ---------------------------------------------------------------*/
441
442 int
__printf_arginfo_ptr(const struct printf_info * pi __unused,size_t n,int * argt)443 __printf_arginfo_ptr(const struct printf_info *pi __unused, size_t n, int *argt)
444 {
445
446 assert (n > 0);
447 argt[0] = PA_POINTER;
448 return (1);
449 }
450
451 int
__printf_render_ptr(struct __printf_io * io,const struct printf_info * pi,const void * const * arg)452 __printf_render_ptr(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
453 {
454 struct printf_info p2;
455 uintmax_t u;
456 const void *p;
457
458 /*-
459 * ``The argument shall be a pointer to void. The
460 * value of the pointer is converted to a sequence
461 * of printable characters, in an implementation-
462 * defined manner.''
463 * -- ANSI X3J11
464 */
465 u = (uintmax_t)(uintptr_t) *((void **)arg[0]);
466 p2 = *pi;
467
468 p2.spec = 'x';
469 p2.alt = 1;
470 p2.is_long_double = 1;
471 p = &u;
472 return (__printf_render_int(io, &p2, &p));
473 }
474