1 // SPDX-License-Identifier: GPL-2.0-only 2 /* -*- linux-c -*- ------------------------------------------------------- * 3 * 4 * Copyright (C) 1991, 1992 Linus Torvalds 5 * Copyright 2007 rPath, Inc. - All Rights Reserved 6 * 7 * ----------------------------------------------------------------------- */ 8 9 /* 10 * Oh, it's a waste of space, but oh-so-yummy for debugging. 11 */ 12 13 #include <stdarg.h> 14 15 #include <linux/compiler.h> 16 #include <linux/ctype.h> 17 #include <linux/kernel.h> 18 #include <linux/limits.h> 19 #include <linux/string.h> 20 #include <linux/types.h> 21 22 static 23 int skip_atoi(const char **s) 24 { 25 int i = 0; 26 27 while (isdigit(**s)) 28 i = i * 10 + *((*s)++) - '0'; 29 return i; 30 } 31 32 /* 33 * put_dec_full4 handles numbers in the range 0 <= r < 10000. 34 * The multiplier 0xccd is round(2^15/10), and the approximation 35 * r/10 == (r * 0xccd) >> 15 is exact for all r < 16389. 36 */ 37 static 38 void put_dec_full4(char *end, unsigned int r) 39 { 40 int i; 41 42 for (i = 0; i < 3; i++) { 43 unsigned int q = (r * 0xccd) >> 15; 44 *--end = '0' + (r - q * 10); 45 r = q; 46 } 47 *--end = '0' + r; 48 } 49 50 /* put_dec is copied from lib/vsprintf.c with small modifications */ 51 52 /* 53 * Call put_dec_full4 on x % 10000, return x / 10000. 54 * The approximation x/10000 == (x * 0x346DC5D7) >> 43 55 * holds for all x < 1,128,869,999. The largest value this 56 * helper will ever be asked to convert is 1,125,520,955. 57 * (second call in the put_dec code, assuming n is all-ones). 58 */ 59 static 60 unsigned int put_dec_helper4(char *end, unsigned int x) 61 { 62 unsigned int q = (x * 0x346DC5D7ULL) >> 43; 63 64 put_dec_full4(end, x - q * 10000); 65 return q; 66 } 67 68 /* Based on code by Douglas W. Jones found at 69 * <http://www.cs.uiowa.edu/~jones/bcd/decimal.html#sixtyfour> 70 * (with permission from the author). 71 * Performs no 64-bit division and hence should be fast on 32-bit machines. 72 */ 73 static 74 char *put_dec(char *end, unsigned long long n) 75 { 76 unsigned int d3, d2, d1, q, h; 77 char *p = end; 78 79 d1 = ((unsigned int)n >> 16); /* implicit "& 0xffff" */ 80 h = (n >> 32); 81 d2 = (h ) & 0xffff; 82 d3 = (h >> 16); /* implicit "& 0xffff" */ 83 84 /* n = 2^48 d3 + 2^32 d2 + 2^16 d1 + d0 85 = 281_4749_7671_0656 d3 + 42_9496_7296 d2 + 6_5536 d1 + d0 */ 86 q = 656 * d3 + 7296 * d2 + 5536 * d1 + ((unsigned int)n & 0xffff); 87 q = put_dec_helper4(p, q); 88 p -= 4; 89 90 q += 7671 * d3 + 9496 * d2 + 6 * d1; 91 q = put_dec_helper4(p, q); 92 p -= 4; 93 94 q += 4749 * d3 + 42 * d2; 95 q = put_dec_helper4(p, q); 96 p -= 4; 97 98 q += 281 * d3; 99 q = put_dec_helper4(p, q); 100 p -= 4; 101 102 put_dec_full4(p, q); 103 p -= 4; 104 105 /* strip off the extra 0's we printed */ 106 while (p < end && *p == '0') 107 ++p; 108 109 return p; 110 } 111 112 static 113 char *number(char *end, unsigned long long num, int base, char locase) 114 { 115 /* 116 * locase = 0 or 0x20. ORing digits or letters with 'locase' 117 * produces same digits or (maybe lowercased) letters 118 */ 119 120 /* we are called with base 8, 10 or 16, only, thus don't need "G..." */ 121 static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */ 122 123 switch (base) { 124 case 10: 125 if (num != 0) 126 end = put_dec(end, num); 127 break; 128 case 8: 129 for (; num != 0; num >>= 3) 130 *--end = '0' + (num & 07); 131 break; 132 case 16: 133 for (; num != 0; num >>= 4) 134 *--end = digits[num & 0xf] | locase; 135 break; 136 default: 137 unreachable(); 138 }; 139 140 return end; 141 } 142 143 #define ZEROPAD 1 /* pad with zero */ 144 #define SIGN 2 /* unsigned/signed long */ 145 #define PLUS 4 /* show plus */ 146 #define SPACE 8 /* space if plus */ 147 #define LEFT 16 /* left justified */ 148 #define SMALL 32 /* Must be 32 == 0x20 */ 149 #define SPECIAL 64 /* 0x */ 150 151 static 152 int get_flags(const char **fmt) 153 { 154 int flags = 0; 155 156 do { 157 switch (**fmt) { 158 case '-': 159 flags |= LEFT; 160 break; 161 case '+': 162 flags |= PLUS; 163 break; 164 case ' ': 165 flags |= SPACE; 166 break; 167 case '#': 168 flags |= SPECIAL; 169 break; 170 case '0': 171 flags |= ZEROPAD; 172 break; 173 default: 174 return flags; 175 } 176 ++(*fmt); 177 } while (1); 178 } 179 180 static 181 int get_int(const char **fmt, va_list *ap) 182 { 183 if (isdigit(**fmt)) 184 return skip_atoi(fmt); 185 if (**fmt == '*') { 186 ++(*fmt); 187 /* it's the next argument */ 188 return va_arg(*ap, int); 189 } 190 return 0; 191 } 192 193 static 194 unsigned long long get_number(int sign, int qualifier, va_list *ap) 195 { 196 if (sign) { 197 switch (qualifier) { 198 case 'L': 199 return va_arg(*ap, long long); 200 case 'l': 201 return va_arg(*ap, long); 202 case 'h': 203 return (short)va_arg(*ap, int); 204 case 'H': 205 return (signed char)va_arg(*ap, int); 206 default: 207 return va_arg(*ap, int); 208 }; 209 } else { 210 switch (qualifier) { 211 case 'L': 212 return va_arg(*ap, unsigned long long); 213 case 'l': 214 return va_arg(*ap, unsigned long); 215 case 'h': 216 return (unsigned short)va_arg(*ap, int); 217 case 'H': 218 return (unsigned char)va_arg(*ap, int); 219 default: 220 return va_arg(*ap, unsigned int); 221 } 222 } 223 } 224 225 static 226 char get_sign(long long *num, int flags) 227 { 228 if (!(flags & SIGN)) 229 return 0; 230 if (*num < 0) { 231 *num = -(*num); 232 return '-'; 233 } 234 if (flags & PLUS) 235 return '+'; 236 if (flags & SPACE) 237 return ' '; 238 return 0; 239 } 240 241 #define PUTC(c) \ 242 do { \ 243 if (pos < size) \ 244 buf[pos] = (c); \ 245 ++pos; \ 246 } while (0); 247 248 int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap) 249 { 250 /* The maximum space required is to print a 64-bit number in octal */ 251 char tmp[(sizeof(unsigned long long) * 8 + 2) / 3]; 252 char *tmp_end = &tmp[ARRAY_SIZE(tmp)]; 253 long long num; 254 int base; 255 const char *s; 256 size_t len, pos; 257 char sign; 258 259 int flags; /* flags to number() */ 260 261 int field_width; /* width of output field */ 262 int precision; /* min. # of digits for integers; max 263 number of chars for from string */ 264 int qualifier; /* 'h', 'hh', 'l' or 'll' for integer fields */ 265 266 va_list args; 267 268 /* 269 * We want to pass our input va_list to helper functions by reference, 270 * but there's an annoying edge case. If va_list was originally passed 271 * to us by value, we could just pass &ap down to the helpers. This is 272 * the case on, for example, X86_32. 273 * However, on X86_64 (and possibly others), va_list is actually a 274 * size-1 array containing a structure. Our function parameter ap has 275 * decayed from T[1] to T*, and &ap has type T** rather than T(*)[1], 276 * which is what will be expected by a function taking a va_list * 277 * parameter. 278 * One standard way to solve this mess is by creating a copy in a local 279 * variable of type va_list and then passing a pointer to that local 280 * copy instead, which is what we do here. 281 */ 282 va_copy(args, ap); 283 284 for (pos = 0; *fmt; ++fmt) { 285 if (*fmt != '%' || *++fmt == '%') { 286 PUTC(*fmt); 287 continue; 288 } 289 290 /* process flags */ 291 flags = get_flags(&fmt); 292 293 /* get field width */ 294 field_width = get_int(&fmt, &args); 295 if (field_width < 0) { 296 field_width = -field_width; 297 flags |= LEFT; 298 } 299 300 if (flags & LEFT) 301 flags &= ~ZEROPAD; 302 303 /* get the precision */ 304 precision = -1; 305 if (*fmt == '.') { 306 ++fmt; 307 precision = get_int(&fmt, &args); 308 if (precision >= 0) 309 flags &= ~ZEROPAD; 310 } 311 312 /* get the conversion qualifier */ 313 qualifier = -1; 314 if (*fmt == 'h' || *fmt == 'l') { 315 qualifier = *fmt; 316 ++fmt; 317 if (qualifier == *fmt) { 318 qualifier -= 'a'-'A'; 319 ++fmt; 320 } 321 } 322 323 sign = 0; 324 325 switch (*fmt) { 326 case 'c': 327 flags &= LEFT; 328 tmp[0] = (unsigned char)va_arg(args, int); 329 s = tmp; 330 precision = len = 1; 331 goto output; 332 333 case 's': 334 flags &= LEFT; 335 if (precision < 0) 336 precision = INT_MAX; 337 s = va_arg(args, char *); 338 if (!s) 339 s = precision < 6 ? "" : "(null)"; 340 precision = len = strnlen(s, precision); 341 goto output; 342 343 /* integer number formats - set up the flags and "break" */ 344 case 'o': 345 base = 8; 346 break; 347 348 case 'p': 349 if (precision < 0) 350 precision = 2 * sizeof(void *); 351 fallthrough; 352 case 'x': 353 flags |= SMALL; 354 fallthrough; 355 case 'X': 356 base = 16; 357 break; 358 359 case 'd': 360 case 'i': 361 flags |= SIGN; 362 fallthrough; 363 case 'u': 364 flags &= ~SPECIAL; 365 base = 10; 366 break; 367 368 default: 369 /* 370 * Bail out if the conversion specifier is invalid. 371 * There's probably a typo in the format string and the 372 * remaining specifiers are unlikely to match up with 373 * the arguments. 374 */ 375 goto fail; 376 } 377 if (*fmt == 'p') { 378 num = (unsigned long)va_arg(args, void *); 379 } else { 380 num = get_number(flags & SIGN, qualifier, &args); 381 } 382 383 sign = get_sign(&num, flags); 384 if (sign) 385 --field_width; 386 387 s = number(tmp_end, num, base, flags & SMALL); 388 len = tmp_end - s; 389 /* default precision is 1 */ 390 if (precision < 0) 391 precision = 1; 392 /* precision is minimum number of digits to print */ 393 if (precision < len) 394 precision = len; 395 if (flags & SPECIAL) { 396 /* 397 * For octal, a leading 0 is printed only if necessary, 398 * i.e. if it's not already there because of the 399 * precision. 400 */ 401 if (base == 8 && precision == len) 402 ++precision; 403 /* 404 * For hexadecimal, the leading 0x is skipped if the 405 * output is empty, i.e. both the number and the 406 * precision are 0. 407 */ 408 if (base == 16 && precision > 0) 409 field_width -= 2; 410 else 411 flags &= ~SPECIAL; 412 } 413 /* 414 * For zero padding, increase the precision to fill the field 415 * width. 416 */ 417 if ((flags & ZEROPAD) && field_width > precision) 418 precision = field_width; 419 420 output: 421 /* Calculate the padding necessary */ 422 field_width -= precision; 423 /* Leading padding with ' ' */ 424 if (!(flags & LEFT)) 425 while (field_width-- > 0) 426 PUTC(' '); 427 /* sign */ 428 if (sign) 429 PUTC(sign); 430 /* 0x/0X for hexadecimal */ 431 if (flags & SPECIAL) { 432 PUTC('0'); 433 PUTC( 'X' | (flags & SMALL)); 434 } 435 /* Zero padding and excess precision */ 436 while (precision-- > len) 437 PUTC('0'); 438 /* Actual output */ 439 while (len-- > 0) 440 PUTC(*s++); 441 /* Trailing padding with ' ' */ 442 while (field_width-- > 0) 443 PUTC(' '); 444 } 445 fail: 446 va_end(args); 447 448 if (size) 449 buf[min(pos, size-1)] = '\0'; 450 451 return pos; 452 } 453 454 int snprintf(char *buf, size_t size, const char *fmt, ...) 455 { 456 va_list args; 457 int i; 458 459 va_start(args, fmt); 460 i = vsnprintf(buf, size, fmt, args); 461 va_end(args); 462 return i; 463 } 464