1 /* 2 * linux/lib/vsprintf.c 3 * 4 * Copyright (C) 1991, 1992 Linus Torvalds 5 */ 6 7 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ 8 /* 9 * Wirzenius wrote this portably, Torvalds fucked it up :-) 10 */ 11 12 /* 13 * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com> 14 * - changed to provide snprintf and vsnprintf functions 15 * So Feb 1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de> 16 * - scnprintf and vscnprintf 17 */ 18 19 #include <stdarg.h> 20 #include <linux/module.h> 21 #include <linux/types.h> 22 #include <linux/string.h> 23 #include <linux/ctype.h> 24 #include <linux/kernel.h> 25 26 #include <asm/page.h> /* for PAGE_SIZE */ 27 #include <asm/div64.h> 28 29 /** 30 * simple_strtoul - convert a string to an unsigned long 31 * @cp: The start of the string 32 * @endp: A pointer to the end of the parsed string will be placed here 33 * @base: The number base to use 34 */ 35 unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) 36 { 37 unsigned long result = 0,value; 38 39 if (!base) { 40 base = 10; 41 if (*cp == '0') { 42 base = 8; 43 cp++; 44 if ((toupper(*cp) == 'X') && isxdigit(cp[1])) { 45 cp++; 46 base = 16; 47 } 48 } 49 } else if (base == 16) { 50 if (cp[0] == '0' && toupper(cp[1]) == 'X') 51 cp += 2; 52 } 53 while (isxdigit(*cp) && 54 (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) { 55 result = result*base + value; 56 cp++; 57 } 58 if (endp) 59 *endp = (char *)cp; 60 return result; 61 } 62 63 EXPORT_SYMBOL(simple_strtoul); 64 65 /** 66 * simple_strtol - convert a string to a signed long 67 * @cp: The start of the string 68 * @endp: A pointer to the end of the parsed string will be placed here 69 * @base: The number base to use 70 */ 71 long simple_strtol(const char *cp,char **endp,unsigned int base) 72 { 73 if(*cp=='-') 74 return -simple_strtoul(cp+1,endp,base); 75 return simple_strtoul(cp,endp,base); 76 } 77 78 EXPORT_SYMBOL(simple_strtol); 79 80 /** 81 * simple_strtoull - convert a string to an unsigned long long 82 * @cp: The start of the string 83 * @endp: A pointer to the end of the parsed string will be placed here 84 * @base: The number base to use 85 */ 86 unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base) 87 { 88 unsigned long long result = 0,value; 89 90 if (!base) { 91 base = 10; 92 if (*cp == '0') { 93 base = 8; 94 cp++; 95 if ((toupper(*cp) == 'X') && isxdigit(cp[1])) { 96 cp++; 97 base = 16; 98 } 99 } 100 } else if (base == 16) { 101 if (cp[0] == '0' && toupper(cp[1]) == 'X') 102 cp += 2; 103 } 104 while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) 105 ? toupper(*cp) : *cp)-'A'+10) < base) { 106 result = result*base + value; 107 cp++; 108 } 109 if (endp) 110 *endp = (char *)cp; 111 return result; 112 } 113 114 EXPORT_SYMBOL(simple_strtoull); 115 116 /** 117 * simple_strtoll - convert a string to a signed long long 118 * @cp: The start of the string 119 * @endp: A pointer to the end of the parsed string will be placed here 120 * @base: The number base to use 121 */ 122 long long simple_strtoll(const char *cp,char **endp,unsigned int base) 123 { 124 if(*cp=='-') 125 return -simple_strtoull(cp+1,endp,base); 126 return simple_strtoull(cp,endp,base); 127 } 128 129 static int skip_atoi(const char **s) 130 { 131 int i=0; 132 133 while (isdigit(**s)) 134 i = i*10 + *((*s)++) - '0'; 135 return i; 136 } 137 138 #define ZEROPAD 1 /* pad with zero */ 139 #define SIGN 2 /* unsigned/signed long */ 140 #define PLUS 4 /* show plus */ 141 #define SPACE 8 /* space if plus */ 142 #define LEFT 16 /* left justified */ 143 #define SPECIAL 32 /* 0x */ 144 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ 145 146 static char * number(char * buf, char * end, unsigned long long num, int base, int size, int precision, int type) 147 { 148 char c,sign,tmp[66]; 149 const char *digits; 150 static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; 151 static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 152 int i; 153 154 digits = (type & LARGE) ? large_digits : small_digits; 155 if (type & LEFT) 156 type &= ~ZEROPAD; 157 if (base < 2 || base > 36) 158 return NULL; 159 c = (type & ZEROPAD) ? '0' : ' '; 160 sign = 0; 161 if (type & SIGN) { 162 if ((signed long long) num < 0) { 163 sign = '-'; 164 num = - (signed long long) num; 165 size--; 166 } else if (type & PLUS) { 167 sign = '+'; 168 size--; 169 } else if (type & SPACE) { 170 sign = ' '; 171 size--; 172 } 173 } 174 if (type & SPECIAL) { 175 if (base == 16) 176 size -= 2; 177 else if (base == 8) 178 size--; 179 } 180 i = 0; 181 if (num == 0) 182 tmp[i++]='0'; 183 else while (num != 0) 184 tmp[i++] = digits[do_div(num,base)]; 185 if (i > precision) 186 precision = i; 187 size -= precision; 188 if (!(type&(ZEROPAD+LEFT))) { 189 while(size-->0) { 190 if (buf < end) 191 *buf = ' '; 192 ++buf; 193 } 194 } 195 if (sign) { 196 if (buf < end) 197 *buf = sign; 198 ++buf; 199 } 200 if (type & SPECIAL) { 201 if (base==8) { 202 if (buf < end) 203 *buf = '0'; 204 ++buf; 205 } else if (base==16) { 206 if (buf < end) 207 *buf = '0'; 208 ++buf; 209 if (buf < end) 210 *buf = digits[33]; 211 ++buf; 212 } 213 } 214 if (!(type & LEFT)) { 215 while (size-- > 0) { 216 if (buf < end) 217 *buf = c; 218 ++buf; 219 } 220 } 221 while (i < precision--) { 222 if (buf < end) 223 *buf = '0'; 224 ++buf; 225 } 226 while (i-- > 0) { 227 if (buf < end) 228 *buf = tmp[i]; 229 ++buf; 230 } 231 while (size-- > 0) { 232 if (buf < end) 233 *buf = ' '; 234 ++buf; 235 } 236 return buf; 237 } 238 239 /** 240 * vsnprintf - Format a string and place it in a buffer 241 * @buf: The buffer to place the result into 242 * @size: The size of the buffer, including the trailing null space 243 * @fmt: The format string to use 244 * @args: Arguments for the format string 245 * 246 * The return value is the number of characters which would 247 * be generated for the given input, excluding the trailing 248 * '\0', as per ISO C99. If you want to have the exact 249 * number of characters written into @buf as return value 250 * (not including the trailing '\0'), use vscnprintf(). If the 251 * return is greater than or equal to @size, the resulting 252 * string is truncated. 253 * 254 * Call this function if you are already dealing with a va_list. 255 * You probably want snprintf() instead. 256 */ 257 int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) 258 { 259 int len; 260 unsigned long long num; 261 int i, base; 262 char *str, *end, c; 263 const char *s; 264 265 int flags; /* flags to number() */ 266 267 int field_width; /* width of output field */ 268 int precision; /* min. # of digits for integers; max 269 number of chars for from string */ 270 int qualifier; /* 'h', 'l', or 'L' for integer fields */ 271 /* 'z' support added 23/7/1999 S.H. */ 272 /* 'z' changed to 'Z' --davidm 1/25/99 */ 273 /* 't' added for ptrdiff_t */ 274 275 /* Reject out-of-range values early. Large positive sizes are 276 used for unknown buffer sizes. */ 277 if (unlikely((int) size < 0)) { 278 /* There can be only one.. */ 279 static int warn = 1; 280 WARN_ON(warn); 281 warn = 0; 282 return 0; 283 } 284 285 str = buf; 286 end = buf + size; 287 288 /* Make sure end is always >= buf */ 289 if (end < buf) { 290 end = ((void *)-1); 291 size = end - buf; 292 } 293 294 for (; *fmt ; ++fmt) { 295 if (*fmt != '%') { 296 if (str < end) 297 *str = *fmt; 298 ++str; 299 continue; 300 } 301 302 /* process flags */ 303 flags = 0; 304 repeat: 305 ++fmt; /* this also skips first '%' */ 306 switch (*fmt) { 307 case '-': flags |= LEFT; goto repeat; 308 case '+': flags |= PLUS; goto repeat; 309 case ' ': flags |= SPACE; goto repeat; 310 case '#': flags |= SPECIAL; goto repeat; 311 case '0': flags |= ZEROPAD; goto repeat; 312 } 313 314 /* get field width */ 315 field_width = -1; 316 if (isdigit(*fmt)) 317 field_width = skip_atoi(&fmt); 318 else if (*fmt == '*') { 319 ++fmt; 320 /* it's the next argument */ 321 field_width = va_arg(args, int); 322 if (field_width < 0) { 323 field_width = -field_width; 324 flags |= LEFT; 325 } 326 } 327 328 /* get the precision */ 329 precision = -1; 330 if (*fmt == '.') { 331 ++fmt; 332 if (isdigit(*fmt)) 333 precision = skip_atoi(&fmt); 334 else if (*fmt == '*') { 335 ++fmt; 336 /* it's the next argument */ 337 precision = va_arg(args, int); 338 } 339 if (precision < 0) 340 precision = 0; 341 } 342 343 /* get the conversion qualifier */ 344 qualifier = -1; 345 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || 346 *fmt =='Z' || *fmt == 'z' || *fmt == 't') { 347 qualifier = *fmt; 348 ++fmt; 349 if (qualifier == 'l' && *fmt == 'l') { 350 qualifier = 'L'; 351 ++fmt; 352 } 353 } 354 355 /* default base */ 356 base = 10; 357 358 switch (*fmt) { 359 case 'c': 360 if (!(flags & LEFT)) { 361 while (--field_width > 0) { 362 if (str < end) 363 *str = ' '; 364 ++str; 365 } 366 } 367 c = (unsigned char) va_arg(args, int); 368 if (str < end) 369 *str = c; 370 ++str; 371 while (--field_width > 0) { 372 if (str < end) 373 *str = ' '; 374 ++str; 375 } 376 continue; 377 378 case 's': 379 s = va_arg(args, char *); 380 if ((unsigned long)s < PAGE_SIZE) 381 s = "<NULL>"; 382 383 len = strnlen(s, precision); 384 385 if (!(flags & LEFT)) { 386 while (len < field_width--) { 387 if (str < end) 388 *str = ' '; 389 ++str; 390 } 391 } 392 for (i = 0; i < len; ++i) { 393 if (str < end) 394 *str = *s; 395 ++str; ++s; 396 } 397 while (len < field_width--) { 398 if (str < end) 399 *str = ' '; 400 ++str; 401 } 402 continue; 403 404 case 'p': 405 if (field_width == -1) { 406 field_width = 2*sizeof(void *); 407 flags |= ZEROPAD; 408 } 409 str = number(str, end, 410 (unsigned long) va_arg(args, void *), 411 16, field_width, precision, flags); 412 continue; 413 414 415 case 'n': 416 /* FIXME: 417 * What does C99 say about the overflow case here? */ 418 if (qualifier == 'l') { 419 long * ip = va_arg(args, long *); 420 *ip = (str - buf); 421 } else if (qualifier == 'Z' || qualifier == 'z') { 422 size_t * ip = va_arg(args, size_t *); 423 *ip = (str - buf); 424 } else { 425 int * ip = va_arg(args, int *); 426 *ip = (str - buf); 427 } 428 continue; 429 430 case '%': 431 if (str < end) 432 *str = '%'; 433 ++str; 434 continue; 435 436 /* integer number formats - set up the flags and "break" */ 437 case 'o': 438 base = 8; 439 break; 440 441 case 'X': 442 flags |= LARGE; 443 case 'x': 444 base = 16; 445 break; 446 447 case 'd': 448 case 'i': 449 flags |= SIGN; 450 case 'u': 451 break; 452 453 default: 454 if (str < end) 455 *str = '%'; 456 ++str; 457 if (*fmt) { 458 if (str < end) 459 *str = *fmt; 460 ++str; 461 } else { 462 --fmt; 463 } 464 continue; 465 } 466 if (qualifier == 'L') 467 num = va_arg(args, long long); 468 else if (qualifier == 'l') { 469 num = va_arg(args, unsigned long); 470 if (flags & SIGN) 471 num = (signed long) num; 472 } else if (qualifier == 'Z' || qualifier == 'z') { 473 num = va_arg(args, size_t); 474 } else if (qualifier == 't') { 475 num = va_arg(args, ptrdiff_t); 476 } else if (qualifier == 'h') { 477 num = (unsigned short) va_arg(args, int); 478 if (flags & SIGN) 479 num = (signed short) num; 480 } else { 481 num = va_arg(args, unsigned int); 482 if (flags & SIGN) 483 num = (signed int) num; 484 } 485 str = number(str, end, num, base, 486 field_width, precision, flags); 487 } 488 if (size > 0) { 489 if (str < end) 490 *str = '\0'; 491 else 492 end[-1] = '\0'; 493 } 494 /* the trailing null byte doesn't count towards the total */ 495 return str-buf; 496 } 497 498 EXPORT_SYMBOL(vsnprintf); 499 500 /** 501 * vscnprintf - Format a string and place it in a buffer 502 * @buf: The buffer to place the result into 503 * @size: The size of the buffer, including the trailing null space 504 * @fmt: The format string to use 505 * @args: Arguments for the format string 506 * 507 * The return value is the number of characters which have been written into 508 * the @buf not including the trailing '\0'. If @size is <= 0 the function 509 * returns 0. 510 * 511 * Call this function if you are already dealing with a va_list. 512 * You probably want scnprintf() instead. 513 */ 514 int vscnprintf(char *buf, size_t size, const char *fmt, va_list args) 515 { 516 int i; 517 518 i=vsnprintf(buf,size,fmt,args); 519 return (i >= size) ? (size - 1) : i; 520 } 521 522 EXPORT_SYMBOL(vscnprintf); 523 524 /** 525 * snprintf - Format a string and place it in a buffer 526 * @buf: The buffer to place the result into 527 * @size: The size of the buffer, including the trailing null space 528 * @fmt: The format string to use 529 * @...: Arguments for the format string 530 * 531 * The return value is the number of characters which would be 532 * generated for the given input, excluding the trailing null, 533 * as per ISO C99. If the return is greater than or equal to 534 * @size, the resulting string is truncated. 535 */ 536 int snprintf(char * buf, size_t size, const char *fmt, ...) 537 { 538 va_list args; 539 int i; 540 541 va_start(args, fmt); 542 i=vsnprintf(buf,size,fmt,args); 543 va_end(args); 544 return i; 545 } 546 547 EXPORT_SYMBOL(snprintf); 548 549 /** 550 * scnprintf - Format a string and place it in a buffer 551 * @buf: The buffer to place the result into 552 * @size: The size of the buffer, including the trailing null space 553 * @fmt: The format string to use 554 * @...: Arguments for the format string 555 * 556 * The return value is the number of characters written into @buf not including 557 * the trailing '\0'. If @size is <= 0 the function returns 0. 558 */ 559 560 int scnprintf(char * buf, size_t size, const char *fmt, ...) 561 { 562 va_list args; 563 int i; 564 565 va_start(args, fmt); 566 i = vsnprintf(buf, size, fmt, args); 567 va_end(args); 568 return (i >= size) ? (size - 1) : i; 569 } 570 EXPORT_SYMBOL(scnprintf); 571 572 /** 573 * vsprintf - Format a string and place it in a buffer 574 * @buf: The buffer to place the result into 575 * @fmt: The format string to use 576 * @args: Arguments for the format string 577 * 578 * The function returns the number of characters written 579 * into @buf. Use vsnprintf() or vscnprintf() in order to avoid 580 * buffer overflows. 581 * 582 * Call this function if you are already dealing with a va_list. 583 * You probably want sprintf() instead. 584 */ 585 int vsprintf(char *buf, const char *fmt, va_list args) 586 { 587 return vsnprintf(buf, INT_MAX, fmt, args); 588 } 589 590 EXPORT_SYMBOL(vsprintf); 591 592 /** 593 * sprintf - Format a string and place it in a buffer 594 * @buf: The buffer to place the result into 595 * @fmt: The format string to use 596 * @...: Arguments for the format string 597 * 598 * The function returns the number of characters written 599 * into @buf. Use snprintf() or scnprintf() in order to avoid 600 * buffer overflows. 601 */ 602 int sprintf(char * buf, const char *fmt, ...) 603 { 604 va_list args; 605 int i; 606 607 va_start(args, fmt); 608 i=vsnprintf(buf, INT_MAX, fmt, args); 609 va_end(args); 610 return i; 611 } 612 613 EXPORT_SYMBOL(sprintf); 614 615 /** 616 * vsscanf - Unformat a buffer into a list of arguments 617 * @buf: input buffer 618 * @fmt: format of buffer 619 * @args: arguments 620 */ 621 int vsscanf(const char * buf, const char * fmt, va_list args) 622 { 623 const char *str = buf; 624 char *next; 625 char digit; 626 int num = 0; 627 int qualifier; 628 int base; 629 int field_width; 630 int is_sign = 0; 631 632 while(*fmt && *str) { 633 /* skip any white space in format */ 634 /* white space in format matchs any amount of 635 * white space, including none, in the input. 636 */ 637 if (isspace(*fmt)) { 638 while (isspace(*fmt)) 639 ++fmt; 640 while (isspace(*str)) 641 ++str; 642 } 643 644 /* anything that is not a conversion must match exactly */ 645 if (*fmt != '%' && *fmt) { 646 if (*fmt++ != *str++) 647 break; 648 continue; 649 } 650 651 if (!*fmt) 652 break; 653 ++fmt; 654 655 /* skip this conversion. 656 * advance both strings to next white space 657 */ 658 if (*fmt == '*') { 659 while (!isspace(*fmt) && *fmt) 660 fmt++; 661 while (!isspace(*str) && *str) 662 str++; 663 continue; 664 } 665 666 /* get field width */ 667 field_width = -1; 668 if (isdigit(*fmt)) 669 field_width = skip_atoi(&fmt); 670 671 /* get conversion qualifier */ 672 qualifier = -1; 673 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || 674 *fmt == 'Z' || *fmt == 'z') { 675 qualifier = *fmt++; 676 if (unlikely(qualifier == *fmt)) { 677 if (qualifier == 'h') { 678 qualifier = 'H'; 679 fmt++; 680 } else if (qualifier == 'l') { 681 qualifier = 'L'; 682 fmt++; 683 } 684 } 685 } 686 base = 10; 687 is_sign = 0; 688 689 if (!*fmt || !*str) 690 break; 691 692 switch(*fmt++) { 693 case 'c': 694 { 695 char *s = (char *) va_arg(args,char*); 696 if (field_width == -1) 697 field_width = 1; 698 do { 699 *s++ = *str++; 700 } while (--field_width > 0 && *str); 701 num++; 702 } 703 continue; 704 case 's': 705 { 706 char *s = (char *) va_arg(args, char *); 707 if(field_width == -1) 708 field_width = INT_MAX; 709 /* first, skip leading white space in buffer */ 710 while (isspace(*str)) 711 str++; 712 713 /* now copy until next white space */ 714 while (*str && !isspace(*str) && field_width--) { 715 *s++ = *str++; 716 } 717 *s = '\0'; 718 num++; 719 } 720 continue; 721 case 'n': 722 /* return number of characters read so far */ 723 { 724 int *i = (int *)va_arg(args,int*); 725 *i = str - buf; 726 } 727 continue; 728 case 'o': 729 base = 8; 730 break; 731 case 'x': 732 case 'X': 733 base = 16; 734 break; 735 case 'i': 736 base = 0; 737 case 'd': 738 is_sign = 1; 739 case 'u': 740 break; 741 case '%': 742 /* looking for '%' in str */ 743 if (*str++ != '%') 744 return num; 745 continue; 746 default: 747 /* invalid format; stop here */ 748 return num; 749 } 750 751 /* have some sort of integer conversion. 752 * first, skip white space in buffer. 753 */ 754 while (isspace(*str)) 755 str++; 756 757 digit = *str; 758 if (is_sign && digit == '-') 759 digit = *(str + 1); 760 761 if (!digit 762 || (base == 16 && !isxdigit(digit)) 763 || (base == 10 && !isdigit(digit)) 764 || (base == 8 && (!isdigit(digit) || digit > '7')) 765 || (base == 0 && !isdigit(digit))) 766 break; 767 768 switch(qualifier) { 769 case 'H': /* that's 'hh' in format */ 770 if (is_sign) { 771 signed char *s = (signed char *) va_arg(args,signed char *); 772 *s = (signed char) simple_strtol(str,&next,base); 773 } else { 774 unsigned char *s = (unsigned char *) va_arg(args, unsigned char *); 775 *s = (unsigned char) simple_strtoul(str, &next, base); 776 } 777 break; 778 case 'h': 779 if (is_sign) { 780 short *s = (short *) va_arg(args,short *); 781 *s = (short) simple_strtol(str,&next,base); 782 } else { 783 unsigned short *s = (unsigned short *) va_arg(args, unsigned short *); 784 *s = (unsigned short) simple_strtoul(str, &next, base); 785 } 786 break; 787 case 'l': 788 if (is_sign) { 789 long *l = (long *) va_arg(args,long *); 790 *l = simple_strtol(str,&next,base); 791 } else { 792 unsigned long *l = (unsigned long*) va_arg(args,unsigned long*); 793 *l = simple_strtoul(str,&next,base); 794 } 795 break; 796 case 'L': 797 if (is_sign) { 798 long long *l = (long long*) va_arg(args,long long *); 799 *l = simple_strtoll(str,&next,base); 800 } else { 801 unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*); 802 *l = simple_strtoull(str,&next,base); 803 } 804 break; 805 case 'Z': 806 case 'z': 807 { 808 size_t *s = (size_t*) va_arg(args,size_t*); 809 *s = (size_t) simple_strtoul(str,&next,base); 810 } 811 break; 812 default: 813 if (is_sign) { 814 int *i = (int *) va_arg(args, int*); 815 *i = (int) simple_strtol(str,&next,base); 816 } else { 817 unsigned int *i = (unsigned int*) va_arg(args, unsigned int*); 818 *i = (unsigned int) simple_strtoul(str,&next,base); 819 } 820 break; 821 } 822 num++; 823 824 if (!next) 825 break; 826 str = next; 827 } 828 return num; 829 } 830 831 EXPORT_SYMBOL(vsscanf); 832 833 /** 834 * sscanf - Unformat a buffer into a list of arguments 835 * @buf: input buffer 836 * @fmt: formatting of buffer 837 * @...: resulting arguments 838 */ 839 int sscanf(const char * buf, const char * fmt, ...) 840 { 841 va_list args; 842 int i; 843 844 va_start(args,fmt); 845 i = vsscanf(buf,fmt,args); 846 va_end(args); 847 return i; 848 } 849 850 EXPORT_SYMBOL(sscanf); 851 852 853 /* Simplified asprintf. */ 854 char *kasprintf(gfp_t gfp, const char *fmt, ...) 855 { 856 va_list ap; 857 unsigned int len; 858 char *p; 859 860 va_start(ap, fmt); 861 len = vsnprintf(NULL, 0, fmt, ap); 862 va_end(ap); 863 864 p = kmalloc(len+1, gfp); 865 if (!p) 866 return NULL; 867 va_start(ap, fmt); 868 vsnprintf(p, len+1, fmt, ap); 869 va_end(ap); 870 return p; 871 } 872 873 EXPORT_SYMBOL(kasprintf); 874