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