1153486Sphk/*- 2153486Sphk * Copyright (c) 2005 Poul-Henning Kamp 3153486Sphk * Copyright (c) 1990, 1993 4153486Sphk * The Regents of the University of California. All rights reserved. 5153486Sphk * 6153486Sphk * This code is derived from software contributed to Berkeley by 7153486Sphk * Chris Torek. 8153486Sphk * 9153486Sphk * Redistribution and use in source and binary forms, with or without 10153486Sphk * modification, are permitted provided that the following conditions 11153486Sphk * are met: 12153486Sphk * 1. Redistributions of source code must retain the above copyright 13153486Sphk * notice, this list of conditions and the following disclaimer. 14153486Sphk * 2. Redistributions in binary form must reproduce the above copyright 15153486Sphk * notice, this list of conditions and the following disclaimer in the 16153486Sphk * documentation and/or other materials provided with the distribution. 17153486Sphk * 3. Neither the name of the University nor the names of its contributors 18153486Sphk * may be used to endorse or promote products derived from this software 19153486Sphk * without specific prior written permission. 20153486Sphk * 21153486Sphk * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22153486Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23153486Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24153486Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25153486Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26153486Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27153486Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28153486Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29153486Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30153486Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31153486Sphk * SUCH DAMAGE. 32153486Sphk * 33153486Sphk * $FreeBSD: releng/11.0/lib/libc/stdio/xprintf_int.c 153641 2005-12-22 14:23:54Z cognet $ 34153486Sphk */ 35153486Sphk 36153486Sphk#include <namespace.h> 37153486Sphk#include <err.h> 38153486Sphk#include <sys/types.h> 39153486Sphk#include <stddef.h> 40153486Sphk#include <stdlib.h> 41153486Sphk#include <stdio.h> 42153486Sphk#include <limits.h> 43153486Sphk#include <locale.h> 44153486Sphk#include <stdint.h> 45153486Sphk#include <assert.h> 46153486Sphk#include <namespace.h> 47153486Sphk#include <string.h> 48153486Sphk#include <wchar.h> 49153486Sphk#include <un-namespace.h> 50153486Sphk 51153486Sphk#include "printf.h" 52153486Sphk 53153486Sphk/* private stuff -----------------------------------------------------*/ 54153486Sphk 55153486Sphkunion arg { 56153486Sphk int intarg; 57153486Sphk u_int uintarg; 58153486Sphk long longarg; 59153486Sphk u_long ulongarg; 60153486Sphk intmax_t intmaxarg; 61153486Sphk uintmax_t uintmaxarg; 62153486Sphk}; 63153486Sphk 64153486Sphk/* 65153486Sphk * Macros for converting digits to letters and vice versa 66153486Sphk */ 67153486Sphk#define to_char(n) ((n) + '0') 68153486Sphk 69153486Sphk/* various globals ---------------------------------------------------*/ 70153486Sphk 71153486Sphk/* 72153486Sphk * The size of the buffer we use for integer conversions. 73153486Sphk * Technically, we would need the most space for base 10 74153486Sphk * conversions with thousands' grouping characters between 75153486Sphk * each pair of digits: 60 digits for 128 bit intmax_t. 76153486Sphk * Use a bit more for better alignment of stuff. 77153486Sphk */ 78153486Sphk#define BUF 64 79153486Sphk 80153486Sphk/* misc --------------------------------------------------------------*/ 81153486Sphk 82153486Sphk/* 83153486Sphk * Convert an unsigned long to ASCII for printf purposes, returning 84153486Sphk * a pointer to the first character of the string representation. 85153486Sphk * Octal numbers can be forced to have a leading zero; hex numbers 86153486Sphk * use the given digits. 87153486Sphk */ 88153486Sphkstatic char * 89153486Sphk__ultoa(u_long val, char *endp, int base, const char *xdigs, 90153486Sphk int needgrp, char thousep, const char *grp) 91153486Sphk{ 92153486Sphk char *cp = endp; 93153486Sphk long sval; 94153486Sphk int ndig; 95153486Sphk 96153486Sphk /* 97153486Sphk * Handle the three cases separately, in the hope of getting 98153486Sphk * better/faster code. 99153486Sphk */ 100153486Sphk switch (base) { 101153486Sphk case 10: 102153486Sphk if (val < 10) { /* many numbers are 1 digit */ 103153486Sphk *--cp = to_char(val); 104153486Sphk return (cp); 105153486Sphk } 106153486Sphk ndig = 0; 107153486Sphk /* 108153486Sphk * On many machines, unsigned arithmetic is harder than 109153486Sphk * signed arithmetic, so we do at most one unsigned mod and 110153486Sphk * divide; this is sufficient to reduce the range of 111153486Sphk * the incoming value to where signed arithmetic works. 112153486Sphk */ 113153486Sphk if (val > LONG_MAX) { 114153486Sphk *--cp = to_char(val % 10); 115153486Sphk ndig++; 116153486Sphk sval = val / 10; 117153486Sphk } else 118153486Sphk sval = val; 119153486Sphk do { 120153486Sphk *--cp = to_char(sval % 10); 121153486Sphk ndig++; 122153486Sphk /* 123153486Sphk * If (*grp == CHAR_MAX) then no more grouping 124153486Sphk * should be performed. 125153486Sphk */ 126153486Sphk if (needgrp && ndig == *grp && *grp != CHAR_MAX 127153486Sphk && sval > 9) { 128153486Sphk *--cp = thousep; 129153486Sphk ndig = 0; 130153486Sphk /* 131153486Sphk * If (*(grp+1) == '\0') then we have to 132153486Sphk * use *grp character (last grouping rule) 133153486Sphk * for all next cases 134153486Sphk */ 135153486Sphk if (*(grp+1) != '\0') 136153486Sphk grp++; 137153486Sphk } 138153486Sphk sval /= 10; 139153486Sphk } while (sval != 0); 140153486Sphk break; 141153486Sphk 142153486Sphk case 8: 143153486Sphk do { 144153486Sphk *--cp = to_char(val & 7); 145153486Sphk val >>= 3; 146153486Sphk } while (val); 147153486Sphk break; 148153486Sphk 149153486Sphk case 16: 150153486Sphk do { 151153486Sphk *--cp = xdigs[val & 15]; 152153486Sphk val >>= 4; 153153486Sphk } while (val); 154153486Sphk break; 155153486Sphk 156153486Sphk default: /* oops */ 157153486Sphk assert(base == 16); 158153486Sphk } 159153486Sphk return (cp); 160153486Sphk} 161153486Sphk 162153486Sphk 163153486Sphk/* Identical to __ultoa, but for intmax_t. */ 164153486Sphkstatic char * 165153486Sphk__ujtoa(uintmax_t val, char *endp, int base, const char *xdigs, 166153486Sphk int needgrp, char thousep, const char *grp) 167153486Sphk{ 168153486Sphk char *cp = endp; 169153486Sphk intmax_t sval; 170153486Sphk int ndig; 171153486Sphk 172153486Sphk switch (base) { 173153486Sphk case 10: 174153486Sphk if (val < 10) { 175153486Sphk *--cp = to_char(val % 10); 176153486Sphk return (cp); 177153486Sphk } 178153486Sphk ndig = 0; 179153486Sphk if (val > INTMAX_MAX) { 180153486Sphk *--cp = to_char(val % 10); 181153486Sphk ndig++; 182153486Sphk sval = val / 10; 183153486Sphk } else 184153486Sphk sval = val; 185153486Sphk do { 186153486Sphk *--cp = to_char(sval % 10); 187153486Sphk ndig++; 188153486Sphk /* 189153486Sphk * If (*grp == CHAR_MAX) then no more grouping 190153486Sphk * should be performed. 191153486Sphk */ 192153486Sphk if (needgrp && *grp != CHAR_MAX && ndig == *grp 193153486Sphk && sval > 9) { 194153486Sphk *--cp = thousep; 195153486Sphk ndig = 0; 196153486Sphk /* 197153486Sphk * If (*(grp+1) == '\0') then we have to 198153486Sphk * use *grp character (last grouping rule) 199153486Sphk * for all next cases 200153486Sphk */ 201153486Sphk if (*(grp+1) != '\0') 202153486Sphk grp++; 203153486Sphk } 204153486Sphk sval /= 10; 205153486Sphk } while (sval != 0); 206153486Sphk break; 207153486Sphk 208153486Sphk case 8: 209153486Sphk do { 210153486Sphk *--cp = to_char(val & 7); 211153486Sphk val >>= 3; 212153486Sphk } while (val); 213153486Sphk break; 214153486Sphk 215153486Sphk case 16: 216153486Sphk do { 217153486Sphk *--cp = xdigs[val & 15]; 218153486Sphk val >>= 4; 219153486Sphk } while (val); 220153486Sphk break; 221153486Sphk 222153486Sphk default: 223153486Sphk abort(); 224153486Sphk } 225153486Sphk return (cp); 226153486Sphk} 227153486Sphk 228153486Sphk 229153486Sphk/* 'd' ---------------------------------------------------------------*/ 230153486Sphk 231153486Sphkint 232153486Sphk__printf_arginfo_int(const struct printf_info *pi, size_t n, int *argt) 233153486Sphk{ 234153486Sphk assert (n > 0); 235153486Sphk argt[0] = PA_INT; 236153486Sphk if (pi->is_ptrdiff) 237153486Sphk argt[0] |= PA_FLAG_PTRDIFF; 238153486Sphk else if (pi->is_size) 239153486Sphk argt[0] |= PA_FLAG_SIZE; 240153486Sphk else if (pi->is_long) 241153486Sphk argt[0] |= PA_FLAG_LONG; 242153486Sphk else if (pi->is_intmax) 243153486Sphk argt[0] |= PA_FLAG_INTMAX; 244153486Sphk else if (pi->is_quad) 245153486Sphk argt[0] |= PA_FLAG_QUAD; 246153486Sphk else if (pi->is_long_double) 247153486Sphk argt[0] |= PA_FLAG_LONG_LONG; 248153486Sphk else if (pi->is_short) 249153486Sphk argt[0] |= PA_FLAG_SHORT; 250153486Sphk else if (pi->is_char) 251153486Sphk argt[0] = PA_CHAR; 252153486Sphk return (1); 253153486Sphk} 254153486Sphk 255153486Sphkint 256153486Sphk__printf_render_int(struct __printf_io *io, const struct printf_info *pi, const void *const *arg) 257153486Sphk{ 258153486Sphk const union arg *argp; 259153486Sphk char buf[BUF]; 260153486Sphk char *p, *pe; 261153486Sphk char ns, l; 262153486Sphk int rdx, sign, zext, ngrp; 263153486Sphk const char *nalt, *digit; 264153486Sphk char thousands_sep; /* locale specific thousands separator */ 265153486Sphk const char *grouping; /* locale specific numeric grouping rules */ 266153486Sphk uintmax_t uu; 267153486Sphk int ret; 268153486Sphk 269153486Sphk ret = 0; 270153486Sphk nalt = NULL; 271153486Sphk digit = __lowercase_hex; 272153486Sphk ns = '\0'; 273153486Sphk pe = buf + sizeof buf - 1; 274153486Sphk 275153486Sphk if (pi->group) { 276153486Sphk thousands_sep = *(localeconv()->thousands_sep); 277153486Sphk grouping = localeconv()->grouping; 278153486Sphk ngrp = 1; 279153486Sphk } else { 280153486Sphk thousands_sep = 0; 281153486Sphk grouping = NULL; 282153486Sphk ngrp = 0; 283153486Sphk } 284153486Sphk 285153486Sphk switch(pi->spec) { 286153486Sphk case 'd': 287153486Sphk case 'i': 288153486Sphk rdx = 10; 289153486Sphk sign = 1; 290153486Sphk break; 291153486Sphk case 'X': 292153486Sphk digit = __uppercase_hex; 293153486Sphk /*FALLTHOUGH*/ 294153486Sphk case 'x': 295153486Sphk rdx = 16; 296153486Sphk sign = 0; 297153486Sphk break; 298153486Sphk case 'u': 299153486Sphk case 'U': 300153486Sphk rdx = 10; 301153486Sphk sign = 0; 302153486Sphk break; 303153486Sphk case 'o': 304153486Sphk case 'O': 305153486Sphk rdx = 8; 306153486Sphk sign = 0; 307153486Sphk break; 308153486Sphk default: 309153486Sphk fprintf(stderr, "pi->spec = '%c'\n", pi->spec); 310153486Sphk assert(1 == 0); 311153486Sphk } 312153486Sphk argp = arg[0]; 313153486Sphk 314153486Sphk if (sign) 315153486Sphk ns = pi->showsign; 316153486Sphk 317153486Sphk if (pi->is_long_double || pi->is_quad || pi->is_intmax || 318153486Sphk pi->is_size || pi->is_ptrdiff) { 319153486Sphk if (sign && argp->intmaxarg < 0) { 320153486Sphk uu = -argp->intmaxarg; 321153486Sphk ns = '-'; 322153486Sphk } else 323153486Sphk uu = argp->uintmaxarg; 324153486Sphk } else if (pi->is_long) { 325153486Sphk if (sign && argp->longarg < 0) { 326153486Sphk uu = (u_long)-argp->longarg; 327153486Sphk ns = '-'; 328153486Sphk } else 329153486Sphk uu = argp->ulongarg; 330153486Sphk } else if (pi->is_short) { 331153486Sphk if (sign && (short)argp->intarg < 0) { 332153486Sphk uu = -(short)argp->intarg; 333153486Sphk ns = '-'; 334153486Sphk } else 335153486Sphk uu = (unsigned short)argp->uintarg; 336153486Sphk } else if (pi->is_char) { 337153641Scognet if (sign && (signed char)argp->intarg < 0) { 338153641Scognet uu = -(signed char)argp->intarg; 339153486Sphk ns = '-'; 340153486Sphk } else 341153486Sphk uu = (unsigned char)argp->uintarg; 342153486Sphk } else { 343153486Sphk if (sign && argp->intarg < 0) { 344153486Sphk uu = (unsigned)-argp->intarg; 345153486Sphk ns = '-'; 346153486Sphk } else 347153486Sphk uu = argp->uintarg; 348153486Sphk } 349153486Sphk if (uu <= ULONG_MAX) 350153486Sphk p = __ultoa(uu, pe, rdx, digit, ngrp, thousands_sep, grouping); 351153486Sphk else 352153486Sphk p = __ujtoa(uu, pe, rdx, digit, ngrp, thousands_sep, grouping); 353153486Sphk 354153486Sphk l = 0; 355153486Sphk if (uu == 0) { 356153486Sphk /*- 357153486Sphk * ``The result of converting a zero value with an 358153486Sphk * explicit precision of zero is no characters.'' 359153486Sphk * -- ANSI X3J11 360153486Sphk * 361153486Sphk * ``The C Standard is clear enough as is. The call 362153486Sphk * printf("%#.0o", 0) should print 0.'' 363153486Sphk * -- Defect Report #151 364153486Sphk */ 365153486Sphk ; 366153486Sphk if (pi->prec == 0 && !(pi->alt && rdx == 8)) 367153486Sphk p = pe; 368153486Sphk } else if (pi->alt) { 369153486Sphk if (rdx == 8) 370153486Sphk *--p = '0'; 371153486Sphk if (rdx == 16) { 372153486Sphk if (pi->spec == 'x') 373153486Sphk nalt = "0x"; 374153486Sphk else 375153486Sphk nalt = "0X"; 376153486Sphk l += 2; 377153486Sphk } 378153486Sphk } 379153486Sphk l += pe - p; 380153486Sphk if (ns) 381153486Sphk l++; 382153486Sphk 383153486Sphk /*- 384153486Sphk * ``... diouXx conversions ... if a precision is 385153486Sphk * specified, the 0 flag will be ignored.'' 386153486Sphk * -- ANSI X3J11 387153486Sphk */ 388153486Sphk if (pi->prec > (pe - p)) 389153486Sphk zext = pi->prec - (pe - p); 390153486Sphk else if (pi->prec != -1) 391153486Sphk zext = 0; 392153486Sphk else if (pi->pad == '0' && pi->width > l && !pi->left) 393153486Sphk zext = pi->width - l; 394153486Sphk else 395153486Sphk zext = 0; 396153486Sphk 397153486Sphk l += zext; 398153486Sphk 399153486Sphk while (zext > 0 && p > buf) { 400153486Sphk *--p = '0'; 401153486Sphk zext--; 402153486Sphk } 403153486Sphk 404153486Sphk if (l < BUF) { 405153486Sphk if (ns) { 406153486Sphk *--p = ns; 407153486Sphk } else if (nalt != NULL) { 408153486Sphk *--p = nalt[1]; 409153486Sphk *--p = nalt[0]; 410153486Sphk } 411153486Sphk if (pi->width > (pe - p) && !pi->left) { 412153486Sphk l = pi->width - (pe - p); 413153486Sphk while (l > 0 && p > buf) { 414153486Sphk *--p = ' '; 415153486Sphk l--; 416153486Sphk } 417153486Sphk if (l) 418153486Sphk ret += __printf_pad(io, l, 0); 419153486Sphk } 420153486Sphk } else { 421153486Sphk if (!pi->left && pi->width > l) 422153486Sphk ret += __printf_pad(io, pi->width - l, 0); 423153486Sphk if (ns != '\0') 424153486Sphk ret += __printf_puts(io, &ns, 1); 425153486Sphk else if (nalt != NULL) 426153486Sphk ret += __printf_puts(io, nalt, 2); 427153486Sphk if (zext > 0) 428153486Sphk ret += __printf_pad(io, zext, 1); 429153486Sphk } 430153486Sphk 431153486Sphk ret += __printf_puts(io, p, pe - p); 432153486Sphk if (pi->width > ret && pi->left) 433153486Sphk ret += __printf_pad(io, pi->width - ret, 0); 434153486Sphk __printf_flush(io); 435153486Sphk return (ret); 436153486Sphk} 437153486Sphk 438153486Sphk/* 'p' ---------------------------------------------------------------*/ 439153486Sphk 440153486Sphkint 441153486Sphk__printf_arginfo_ptr(const struct printf_info *pi __unused, size_t n, int *argt) 442153486Sphk{ 443153486Sphk 444153486Sphk assert (n > 0); 445153486Sphk argt[0] = PA_POINTER; 446153486Sphk return (1); 447153486Sphk} 448153486Sphk 449153486Sphkint 450153486Sphk__printf_render_ptr(struct __printf_io *io, const struct printf_info *pi, const void *const *arg) 451153486Sphk{ 452153486Sphk struct printf_info p2; 453153486Sphk uintmax_t u; 454153486Sphk const void *p; 455153486Sphk 456153486Sphk /*- 457153486Sphk * ``The argument shall be a pointer to void. The 458153486Sphk * value of the pointer is converted to a sequence 459153486Sphk * of printable characters, in an implementation- 460153486Sphk * defined manner.'' 461153486Sphk * -- ANSI X3J11 462153486Sphk */ 463153486Sphk u = (uintmax_t)(uintptr_t) *((void **)arg[0]); 464153486Sphk p2 = *pi; 465153486Sphk 466153486Sphk p2.spec = 'x'; 467153486Sphk p2.alt = 1; 468153486Sphk p2.is_long_double = 1; 469153486Sphk p = &u; 470153486Sphk return (__printf_render_int(io, &p2, &p)); 471153486Sphk} 472