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