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 * 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 * 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 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 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 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 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