1/*- 2 * Copyright (c) 2005 Poul-Henning Kamp 3 * Copyright (c) 1990, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * Chris Torek. 8 * 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. 20 * 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. 32 * 33 * $FreeBSD: src/lib/libc/stdio/xprintf_int.c,v 1.2 2005/12/22 14:23:54 cognet Exp $ 34 */ 35 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 <namespace.h> 47#include <string.h> 48#include <wchar.h> 49#include <un-namespace.h> 50 51#include "printf.h" 52#include "xprintf_private.h" 53 54/* private stuff -----------------------------------------------------*/ 55 56union arg { 57 int intarg; 58 u_int uintarg; 59 long longarg; 60 u_long ulongarg; 61 intmax_t intmaxarg; 62 uintmax_t uintmaxarg; 63}; 64 65/* 66 * Macros for converting digits to letters and vice versa 67 */ 68#define to_char(n) ((n) + '0') 69 70/* various globals ---------------------------------------------------*/ 71 72/* 73 * The size of the buffer we use for integer conversions. 74 * Technically, we would need the most space for base 10 75 * conversions with thousands' grouping characters between 76 * each pair of digits: 39 digits for 128 bit intmax_t plus 77 * 20 grouping characters (which may be multibyte). 78 * Use a bit more for better alignment of stuff. 79 */ 80#define BUF 128 81 82/* misc --------------------------------------------------------------*/ 83 84extern const char *__fix_nogrouping(const char *str); 85 86/* 87 * Convert an unsigned long to ASCII for printf purposes, returning 88 * a pointer to the first character of the string representation. 89 * Octal numbers can be forced to have a leading zero; hex numbers 90 * use the given digits. 91 */ 92static char * 93__ultoa(u_long val, char *endp, int base, const char *xdigs, 94 int needgrp, const char *thousep, int thousep_len, const char *grp) 95{ 96 char *cp = endp; 97 long sval; 98 int ndig; 99 100 /* 101 * Handle the three cases separately, in the hope of getting 102 * better/faster code. 103 */ 104 switch (base) { 105 case 10: 106 if (val < 10) { /* many numbers are 1 digit */ 107 *--cp = to_char(val); 108 return (cp); 109 } 110 ndig = 0; 111 /* 112 * On many machines, unsigned arithmetic is harder than 113 * signed arithmetic, so we do at most one unsigned mod and 114 * divide; this is sufficient to reduce the range of 115 * the incoming value to where signed arithmetic works. 116 */ 117 if (val > LONG_MAX) { 118 *--cp = to_char(val % 10); 119 ndig++; 120 sval = val / 10; 121 } else 122 sval = val; 123 do { 124 *--cp = to_char(sval % 10); 125 ndig++; 126 /* 127 * If (*grp == CHAR_MAX) then no more grouping 128 * should be performed. 129 */ 130 if (needgrp && ndig == *grp && *grp != CHAR_MAX 131 && sval > 9) { 132 cp -= thousep_len; 133 memcpy(cp, thousep, thousep_len); 134 ndig = 0; 135 /* 136 * If (*(grp+1) == '\0') then we have to 137 * use *grp character (last grouping rule) 138 * for all next cases 139 */ 140 if (*(grp+1) != '\0') 141 grp++; 142 } 143 sval /= 10; 144 } while (sval != 0); 145 break; 146 147 case 8: 148 do { 149 *--cp = to_char(val & 7); 150 val >>= 3; 151 } while (val); 152 break; 153 154 case 16: 155 do { 156 *--cp = xdigs[val & 15]; 157 val >>= 4; 158 } while (val); 159 break; 160 161 default: /* oops */ 162 assert(base == 16); 163 } 164 return (cp); 165} 166 167 168/* Identical to __ultoa, but for intmax_t. */ 169static char * 170__ujtoa(uintmax_t val, char *endp, int base, const char *xdigs, 171 int needgrp, const char *thousep, int thousep_len, const char *grp) 172{ 173 char *cp = endp; 174 intmax_t sval; 175 int ndig; 176 177 switch (base) { 178 case 10: 179 if (val < 10) { 180 *--cp = to_char(val % 10); 181 return (cp); 182 } 183 ndig = 0; 184 if (val > INTMAX_MAX) { 185 *--cp = to_char(val % 10); 186 ndig++; 187 sval = val / 10; 188 } else 189 sval = val; 190 do { 191 *--cp = to_char(sval % 10); 192 ndig++; 193 /* 194 * If (*grp == CHAR_MAX) then no more grouping 195 * should be performed. 196 */ 197 if (needgrp && *grp != CHAR_MAX && ndig == *grp 198 && sval > 9) { 199 cp -= thousep_len; 200 memcpy(cp, thousep, thousep_len); 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 break; 220 221 case 16: 222 do { 223 *--cp = xdigs[val & 15]; 224 val >>= 4; 225 } while (val); 226 break; 227 228 default: 229 abort(); 230 } 231 return (cp); 232} 233 234 235/* 'd' ---------------------------------------------------------------*/ 236 237__private_extern__ int 238__printf_arginfo_int(const struct printf_info *pi, size_t n, int *argt) 239{ 240 assert (n > 0); 241 argt[0] = PA_INT; 242#ifdef VECTORS 243 if (pi->is_vec) 244 argt[0] = PA_VECTOR; 245 else 246#endif /* VECTORS */ 247 if (pi->is_ptrdiff) 248 argt[0] |= PA_FLAG_PTRDIFF; 249 else if (pi->is_size) 250 argt[0] |= PA_FLAG_SIZE; 251 else if (pi->is_long) 252 argt[0] |= PA_FLAG_LONG; 253 else if (pi->is_intmax) 254 argt[0] |= PA_FLAG_INTMAX; 255 else if (pi->is_quad) 256 argt[0] |= PA_FLAG_QUAD; 257 else if (pi->is_long_double) 258 argt[0] |= PA_FLAG_LONG_LONG; 259 else if (pi->is_short) 260 argt[0] |= PA_FLAG_SHORT; 261 else if (pi->is_char) 262 argt[0] = PA_CHAR; 263 return (1); 264} 265 266__private_extern__ int 267__printf_render_int(struct __printf_io *io, const struct printf_info *pi, const void *const *arg) 268{ 269 const union arg *argp; 270 char buf[BUF]; 271 char *p, *pe; 272 char ns, l; 273 int rdx, sign, zext, ngrp; 274 const char *nalt, *digit; 275 const char *thousands_sep; /* locale specific thousands separator */ 276 int thousands_sep_len; /* locale specific thousands separator length */ 277 const char *grouping; /* locale specific numeric grouping rules */ 278 uintmax_t uu; 279 int ret; 280 281#ifdef VECTORS 282 if (pi->is_vec) return __xprintf_vector(io, pi, arg); 283#endif /* VECTORS */ 284 285 ret = 0; 286 nalt = NULL; 287 digit = __lowercase_hex; 288 ns = '\0'; 289 pe = buf + sizeof buf - 1; 290 291 if (pi->group) { 292 thousands_sep = localeconv_l(pi->loc)->thousands_sep; 293 thousands_sep_len = strlen(thousands_sep); 294 grouping = __fix_nogrouping(localeconv_l(pi->loc)->grouping); 295 ngrp = 1; 296 } else { 297 thousands_sep = NULL; 298 thousands_sep_len = 0; 299 grouping = NULL; 300 ngrp = 0; 301 } 302 303 switch(pi->spec) { 304 case 'd': 305 case 'i': 306 rdx = 10; 307 sign = 1; 308 break; 309 case 'X': 310 digit = __uppercase_hex; 311 /*FALLTHOUGH*/ 312 case 'x': 313 rdx = 16; 314 sign = 0; 315 break; 316 case 'u': 317 case 'U': 318 rdx = 10; 319 sign = 0; 320 break; 321 case 'o': 322 case 'O': 323 rdx = 8; 324 sign = 0; 325 break; 326 default: 327 fprintf(stderr, "pi->spec = '%c'\n", pi->spec); 328 assert(1 == 0); 329 } 330 argp = arg[0]; 331 332 if (sign) 333 ns = pi->signchar; 334 335 if (pi->is_long_double || pi->is_quad || pi->is_intmax || 336 pi->is_size || pi->is_ptrdiff) { 337 if (sign && argp->intmaxarg < 0) { 338 uu = -argp->intmaxarg; 339 ns = '-'; 340 } else 341 uu = argp->uintmaxarg; 342 } else if (pi->is_long) { 343 if (sign && argp->longarg < 0) { 344 uu = (u_long)-argp->longarg; 345 ns = '-'; 346 } else 347 uu = argp->ulongarg; 348 } else if (pi->is_short) { 349 if (sign && (short)argp->intarg < 0) { 350 uu = -(short)argp->intarg; 351 ns = '-'; 352 } else 353 uu = (unsigned short)argp->uintarg; 354 } else if (pi->is_char) { 355 if (sign && (signed char)argp->intarg < 0) { 356 uu = -(signed char)argp->intarg; 357 ns = '-'; 358 } else 359 uu = (unsigned char)argp->uintarg; 360 } else { 361 if (sign && argp->intarg < 0) { 362 uu = (unsigned)-argp->intarg; 363 ns = '-'; 364 } else 365 uu = argp->uintarg; 366 } 367 if (uu <= ULONG_MAX) 368 p = __ultoa(uu, pe, rdx, digit, ngrp, thousands_sep, thousands_sep_len, grouping); 369 else 370 p = __ujtoa(uu, pe, rdx, digit, ngrp, thousands_sep, thousands_sep_len, grouping); 371 372 l = 0; 373 if (uu == 0) { 374 /*- 375 * ``The result of converting a zero value with an 376 * explicit precision of zero is no characters.'' 377 * -- ANSI X3J11 378 * 379 * ``The C Standard is clear enough as is. The call 380 * printf("%#.0o", 0) should print 0.'' 381 * -- Defect Report #151 382 */ 383 ; 384 if (pi->prec == 0 && !(pi->alt && rdx == 8)) 385 p = pe; 386 } else if (pi->alt) { 387 if (rdx == 8) 388 *--p = '0'; 389 if (rdx == 16) { 390 if (pi->spec == 'x') 391 nalt = "0x"; 392 else 393 nalt = "0X"; 394 l += 2; 395 } 396 } 397 l += pe - p; 398 if (ns) 399 l++; 400 401 /*- 402 * ``... diouXx conversions ... if a precision is 403 * specified, the 0 flag will be ignored.'' 404 * -- ANSI X3J11 405 */ 406 if (pi->prec > (pe - p)) 407 zext = pi->prec - (pe - p); 408 else if (pi->prec != -1) 409 zext = 0; 410 else if (pi->pad == '0' && pi->width > l && !pi->left) 411 zext = pi->width - l; 412 else 413 zext = 0; 414 415 l += zext; 416 417 while (zext > 0 && p > buf) { 418 *--p = '0'; 419 zext--; 420 } 421 422 if (l < BUF) { 423 if (ns) { 424 *--p = ns; 425 } else if (nalt != NULL) { 426 *--p = nalt[1]; 427 *--p = nalt[0]; 428 } 429 if (pi->width > (pe - p) && !pi->left) { 430 l = pi->width - (pe - p); 431 while (l > 0 && p > buf) { 432 *--p = ' '; 433 l--; 434 } 435 if (l) 436 ret += __printf_pad(io, l, 0); 437 } 438 } else { 439 if (!pi->left && pi->width > l) 440 ret += __printf_pad(io, pi->width - l, 0); 441 if (ns != '\0') 442 ret += __printf_puts(io, &ns, 1); 443 else if (nalt != NULL) 444 ret += __printf_puts(io, nalt, 2); 445 if (zext > 0) 446 ret += __printf_pad(io, zext, 1); 447 } 448 449 ret += __printf_puts(io, p, pe - p); 450 if (pi->width > ret && pi->left) 451 ret += __printf_pad(io, pi->width - ret, 0); 452 __printf_flush(io); 453 return (ret); 454} 455 456/* 'p' ---------------------------------------------------------------*/ 457 458__private_extern__ int 459__printf_arginfo_ptr(const struct printf_info *pi __unused, size_t n, int *argt) 460{ 461 462 assert (n > 0); 463#ifdef VECTORS 464 if (pi->is_vec) 465 argt[0] = PA_VECTOR; 466 else 467#endif /* VECTORS */ 468 argt[0] = PA_POINTER; 469 return (1); 470} 471 472__private_extern__ int 473__printf_render_ptr(struct __printf_io *io, const struct printf_info *pi, const void *const *arg) 474{ 475 struct printf_info p2; 476 uintmax_t u; 477 const void *p; 478 479#ifdef VECTORS 480 if (pi->is_vec) return __xprintf_vector(io, pi, arg); 481#endif /* VECTORS */ 482 483 /*- 484 * ``The argument shall be a pointer to void. The 485 * value of the pointer is converted to a sequence 486 * of printable characters, in an implementation- 487 * defined manner.'' 488 * -- ANSI X3J11 489 */ 490 u = (uintmax_t)(uintptr_t) *((void **)arg[0]); 491 p2 = *pi; 492 493 p2.spec = 'x'; 494 p2.alt = 1; 495 p2.is_long_double = 1; 496 p = &u; 497 return (__printf_render_int(io, &p2, &p)); 498} 499