Sync libc/stdio with FreeBSD:
[dragonfly.git] / lib / libc / stdio / xprintf_int.c
blob89cba34bcb15393235c46027bdf9a2efc915a8ca
1 /*-
2 * Copyright (c) 2005 Poul-Henning Kamp
3 * Copyright (c) 1990, 1993
4 * The Regents of the University of California. All rights reserved.
6 * This code is derived from software contributed to Berkeley by
7 * Chris Torek.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
33 * $FreeBSD: src/lib/libc/stdio/xprintf_int.c,v 1.2 2005/12/22 14:23:54 cognet Exp $
36 #include "namespace.h"
37 #include <err.h>
38 #include <sys/types.h>
39 #include <stddef.h>
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <limits.h>
43 #include <locale.h>
44 #include <stdint.h>
45 #include <assert.h>
46 #include <string.h>
47 #include <wchar.h>
48 #include "un-namespace.h"
50 #include "printf.h"
52 /* private stuff -----------------------------------------------------*/
54 union arg {
55 int intarg;
56 u_int uintarg;
57 long longarg;
58 u_long ulongarg;
59 intmax_t intmaxarg;
60 uintmax_t uintmaxarg;
64 * Macros for converting digits to letters and vice versa
66 #define to_char(n) ((n) + '0')
68 /* various globals ---------------------------------------------------*/
71 * The size of the buffer we use for integer conversions.
72 * Technically, we would need the most space for base 10
73 * conversions with thousands' grouping characters between
74 * each pair of digits: 60 digits for 128 bit intmax_t.
75 * Use a bit more for better alignment of stuff.
77 #define BUF 64
79 /* misc --------------------------------------------------------------*/
82 * Convert an unsigned long to ASCII for printf purposes, returning
83 * a pointer to the first character of the string representation.
84 * Octal numbers can be forced to have a leading zero; hex numbers
85 * use the given digits.
87 static char *
88 __ultoa(u_long val, char *endp, int base, const char *xdigs,
89 int needgrp, char thousep, const char *grp)
91 char *cp = endp;
92 long sval;
93 int ndig;
96 * Handle the three cases separately, in the hope of getting
97 * better/faster code.
99 switch (base) {
100 case 10:
101 if (val < 10) { /* many numbers are 1 digit */
102 *--cp = to_char(val);
103 return (cp);
105 ndig = 0;
107 * On many machines, unsigned arithmetic is harder than
108 * signed arithmetic, so we do at most one unsigned mod and
109 * divide; this is sufficient to reduce the range of
110 * the incoming value to where signed arithmetic works.
112 if (val > LONG_MAX) {
113 *--cp = to_char(val % 10);
114 ndig++;
115 sval = val / 10;
116 } else {
117 sval = val;
119 do {
120 *--cp = to_char(sval % 10);
121 ndig++;
123 * If (*grp == CHAR_MAX) then no more grouping
124 * should be performed.
126 if (needgrp && ndig == *grp && *grp != CHAR_MAX
127 && sval > 9) {
128 *--cp = thousep;
129 ndig = 0;
131 * If (*(grp+1) == '\0') then we have to
132 * use *grp character (last grouping rule)
133 * for all next cases
135 if (*(grp+1) != '\0')
136 grp++;
138 sval /= 10;
139 } while (sval != 0);
140 break;
142 case 8:
143 do {
144 *--cp = to_char(val & 7);
145 val >>= 3;
146 } while (val);
147 break;
149 case 16:
150 do {
151 *--cp = xdigs[val & 15];
152 val >>= 4;
153 } while (val);
154 break;
156 default: /* oops */
157 assert(base == 16);
159 return (cp);
163 /* Identical to __ultoa, but for intmax_t. */
164 static char *
165 __ujtoa(uintmax_t val, char *endp, int base, const char *xdigs,
166 int needgrp, char thousep, const char *grp)
168 char *cp = endp;
169 intmax_t sval;
170 int ndig;
172 switch (base) {
173 case 10:
174 if (val < 10) {
175 *--cp = to_char(val % 10);
176 return (cp);
178 ndig = 0;
179 if (val > INTMAX_MAX) {
180 *--cp = to_char(val % 10);
181 ndig++;
182 sval = val / 10;
183 } else {
184 sval = val;
186 do {
187 *--cp = to_char(sval % 10);
188 ndig++;
190 * If (*grp == CHAR_MAX) then no more grouping
191 * should be performed.
193 if (needgrp && *grp != CHAR_MAX && ndig == *grp
194 && sval > 9) {
195 *--cp = thousep;
196 ndig = 0;
198 * If (*(grp+1) == '\0') then we have to
199 * use *grp character (last grouping rule)
200 * for all next cases
202 if (*(grp+1) != '\0')
203 grp++;
205 sval /= 10;
206 } while (sval != 0);
207 break;
209 case 8:
210 do {
211 *--cp = to_char(val & 7);
212 val >>= 3;
213 } while (val);
214 break;
216 case 16:
217 do {
218 *--cp = xdigs[val & 15];
219 val >>= 4;
220 } while (val);
221 break;
223 default:
224 abort();
226 return (cp);
230 /* 'd' ---------------------------------------------------------------*/
233 __printf_arginfo_int(const struct printf_info *pi, size_t n, int *argt)
235 assert (n > 0);
236 argt[0] = PA_INT;
237 if (pi->is_ptrdiff)
238 argt[0] |= PA_FLAG_PTRDIFF;
239 else if (pi->is_size)
240 argt[0] |= PA_FLAG_SIZE;
241 else if (pi->is_long)
242 argt[0] |= PA_FLAG_LONG;
243 else if (pi->is_intmax)
244 argt[0] |= PA_FLAG_INTMAX;
245 else if (pi->is_quad)
246 argt[0] |= PA_FLAG_QUAD;
247 else if (pi->is_long_double)
248 argt[0] |= PA_FLAG_LONG_LONG;
249 else if (pi->is_short)
250 argt[0] |= PA_FLAG_SHORT;
251 else if (pi->is_char)
252 argt[0] = PA_CHAR;
253 return (1);
257 __printf_render_int(struct __printf_io *io, const struct printf_info *pi,
258 const void *const *arg)
260 const union arg *argp;
261 char buf[BUF];
262 char *p, *pe;
263 char ns, l;
264 int rdx, sign, zext, ngrp;
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;
271 ret = 0;
272 nalt = NULL;
273 digit = __lowercase_hex;
274 ns = '\0';
275 pe = buf + sizeof buf - 1;
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;
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);
314 argp = arg[0];
316 if (sign)
317 ns = pi->showsign;
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;
327 } else if (pi->is_long) {
328 if (sign && argp->longarg < 0) {
329 uu = (u_long)-argp->longarg;
330 ns = '-';
331 } else {
332 uu = argp->ulongarg;
334 } else if (pi->is_short) {
335 if (sign && (short)argp->intarg < 0) {
336 uu = -(short)argp->intarg;
337 ns = '-';
338 } else {
339 uu = (unsigned short)argp->uintarg;
341 } else if (pi->is_char) {
342 if (sign && (signed char)argp->intarg < 0) {
343 uu = -(signed char)argp->intarg;
344 ns = '-';
345 } else {
346 uu = (unsigned char)argp->uintarg;
348 } else {
349 if (sign && argp->intarg < 0) {
350 uu = (unsigned)-argp->intarg;
351 ns = '-';
352 } else {
353 uu = argp->uintarg;
356 if (uu <= ULONG_MAX)
357 p = __ultoa(uu, pe, rdx, digit, ngrp, thousands_sep, grouping);
358 else
359 p = __ujtoa(uu, pe, rdx, digit, ngrp, thousands_sep, grouping);
361 l = 0;
362 if (uu == 0) {
364 * ``The result of converting a zero value with an
365 * explicit precision of zero is no characters.''
366 * -- ANSI X3J11
368 * ``The C Standard is clear enough as is. The call
369 * printf("%#.0o", 0) should print 0.''
370 * -- Defect Report #151
372 if (pi->prec == 0 && !(pi->alt && rdx == 8))
373 p = pe;
374 } else if (pi->alt) {
375 if (rdx == 8)
376 *--p = '0';
377 if (rdx == 16) {
378 if (pi->spec == 'x')
379 nalt = "0x";
380 else
381 nalt = "0X";
382 l += 2;
385 l += pe - p;
386 if (ns)
387 l++;
390 * ``... diouXx conversions ... if a precision is
391 * specified, the 0 flag will be ignored.''
392 * -- ANSI X3J11
394 if (pi->prec > (pe - p))
395 zext = pi->prec - (pe - p);
396 else if (pi->prec != -1)
397 zext = 0;
398 else if (pi->pad == '0' && pi->width > l && !pi->left)
399 zext = pi->width - l;
400 else
401 zext = 0;
403 l += zext;
405 while (zext > 0 && p > buf) {
406 *--p = '0';
407 zext--;
410 if (l < BUF) {
411 if (ns) {
412 *--p = ns;
413 } else if (nalt != NULL) {
414 *--p = nalt[1];
415 *--p = nalt[0];
417 if (pi->width > (pe - p) && !pi->left) {
418 l = pi->width - (pe - p);
419 while (l > 0 && p > buf) {
420 *--p = ' ';
421 l--;
423 if (l)
424 ret += __printf_pad(io, l, 0);
426 } else {
427 if (!pi->left && pi->width > l)
428 ret += __printf_pad(io, pi->width - l, 0);
429 if (ns != '\0')
430 ret += __printf_puts(io, &ns, 1);
431 else if (nalt != NULL)
432 ret += __printf_puts(io, nalt, 2);
433 if (zext > 0)
434 ret += __printf_pad(io, zext, 1);
437 ret += __printf_puts(io, p, pe - p);
438 if (pi->width > ret && pi->left)
439 ret += __printf_pad(io, pi->width - ret, 0);
440 __printf_flush(io);
441 return (ret);
444 /* 'p' ---------------------------------------------------------------*/
447 __printf_arginfo_ptr(const struct printf_info *pi __unused, size_t n, int *argt)
450 assert (n > 0);
451 argt[0] = PA_POINTER;
452 return (1);
456 __printf_render_ptr(struct __printf_io *io, const struct printf_info *pi,
457 const void *const *arg)
459 struct printf_info p2;
460 uintmax_t u;
461 const void *p;
464 * ``The argument shall be a pointer to void. The
465 * value of the pointer is converted to a sequence
466 * of printable characters, in an implementation-
467 * defined manner.''
468 * -- ANSI X3J11
470 u = (uintmax_t)(uintptr_t) *((void **)arg[0]);
471 p2 = *pi;
473 p2.spec = 'x';
474 p2.alt = 1;
475 p2.is_long_double = 1;
476 p = &u;
477 return (__printf_render_int(io, &p2, &p));