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 */ 276 if (unlikely((int) size < 0)) { 277 /* There can be only one.. */ 278 static int warn = 1; 279 WARN_ON(warn); 280 warn = 0; 281 return 0; 282 } 283 284 str = buf; 285 end = buf + size - 1; 286 287 if (end < buf - 1) { 288 end = ((void *) -1); 289 size = end - buf + 1; 290 } 291 292 for (; *fmt ; ++fmt) { 293 if (*fmt != '%') { 294 if (str <= end) 295 *str = *fmt; 296 ++str; 297 continue; 298 } 299 300 /* process flags */ 301 flags = 0; 302 repeat: 303 ++fmt; /* this also skips first '%' */ 304 switch (*fmt) { 305 case '-': flags |= LEFT; goto repeat; 306 case '+': flags |= PLUS; goto repeat; 307 case ' ': flags |= SPACE; goto repeat; 308 case '#': flags |= SPECIAL; goto repeat; 309 case '0': flags |= ZEROPAD; goto repeat; 310 } 311 312 /* get field width */ 313 field_width = -1; 314 if (isdigit(*fmt)) 315 field_width = skip_atoi(&fmt); 316 else if (*fmt == '*') { 317 ++fmt; 318 /* it's the next argument */ 319 field_width = va_arg(args, int); 320 if (field_width < 0) { 321 field_width = -field_width; 322 flags |= LEFT; 323 } 324 } 325 326 /* get the precision */ 327 precision = -1; 328 if (*fmt == '.') { 329 ++fmt; 330 if (isdigit(*fmt)) 331 precision = skip_atoi(&fmt); 332 else if (*fmt == '*') { 333 ++fmt; 334 /* it's the next argument */ 335 precision = va_arg(args, int); 336 } 337 if (precision < 0) 338 precision = 0; 339 } 340 341 /* get the conversion qualifier */ 342 qualifier = -1; 343 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || 344 *fmt =='Z' || *fmt == 'z' || *fmt == 't') { 345 qualifier = *fmt; 346 ++fmt; 347 if (qualifier == 'l' && *fmt == 'l') { 348 qualifier = 'L'; 349 ++fmt; 350 } 351 } 352 353 /* default base */ 354 base = 10; 355 356 switch (*fmt) { 357 case 'c': 358 if (!(flags & LEFT)) { 359 while (--field_width > 0) { 360 if (str <= end) 361 *str = ' '; 362 ++str; 363 } 364 } 365 c = (unsigned char) va_arg(args, int); 366 if (str <= end) 367 *str = c; 368 ++str; 369 while (--field_width > 0) { 370 if (str <= end) 371 *str = ' '; 372 ++str; 373 } 374 continue; 375 376 case 's': 377 s = va_arg(args, char *); 378 if ((unsigned long)s < PAGE_SIZE) 379 s = "<NULL>"; 380 381 len = strnlen(s, precision); 382 383 if (!(flags & LEFT)) { 384 while (len < field_width--) { 385 if (str <= end) 386 *str = ' '; 387 ++str; 388 } 389 } 390 for (i = 0; i < len; ++i) { 391 if (str <= end) 392 *str = *s; 393 ++str; ++s; 394 } 395 while (len < field_width--) { 396 if (str <= end) 397 *str = ' '; 398 ++str; 399 } 400 continue; 401 402 case 'p': 403 if (field_width == -1) { 404 field_width = 2*sizeof(void *); 405 flags |= ZEROPAD; 406 } 407 str = number(str, end, 408 (unsigned long) va_arg(args, void *), 409 16, field_width, precision, flags); 410 continue; 411 412 413 case 'n': 414 /* FIXME: 415 * What does C99 say about the overflow case here? */ 416 if (qualifier == 'l') { 417 long * ip = va_arg(args, long *); 418 *ip = (str - buf); 419 } else if (qualifier == 'Z' || qualifier == 'z') { 420 size_t * ip = va_arg(args, size_t *); 421 *ip = (str - buf); 422 } else { 423 int * ip = va_arg(args, int *); 424 *ip = (str - buf); 425 } 426 continue; 427 428 case '%': 429 if (str <= end) 430 *str = '%'; 431 ++str; 432 continue; 433 434 /* integer number formats - set up the flags and "break" */ 435 case 'o': 436 base = 8; 437 break; 438 439 case 'X': 440 flags |= LARGE; 441 case 'x': 442 base = 16; 443 break; 444 445 case 'd': 446 case 'i': 447 flags |= SIGN; 448 case 'u': 449 break; 450 451 default: 452 if (str <= end) 453 *str = '%'; 454 ++str; 455 if (*fmt) { 456 if (str <= end) 457 *str = *fmt; 458 ++str; 459 } else { 460 --fmt; 461 } 462 continue; 463 } 464 if (qualifier == 'L') 465 num = va_arg(args, long long); 466 else if (qualifier == 'l') { 467 num = va_arg(args, unsigned long); 468 if (flags & SIGN) 469 num = (signed long) num; 470 } else if (qualifier == 'Z' || qualifier == 'z') { 471 num = va_arg(args, size_t); 472 } else if (qualifier == 't') { 473 num = va_arg(args, ptrdiff_t); 474 } else if (qualifier == 'h') { 475 num = (unsigned short) va_arg(args, int); 476 if (flags & SIGN) 477 num = (signed short) num; 478 } else { 479 num = va_arg(args, unsigned int); 480 if (flags & SIGN) 481 num = (signed int) num; 482 } 483 str = number(str, end, num, base, 484 field_width, precision, flags); 485 } 486 if (str <= end) 487 *str = '\0'; 488 else if (size > 0) 489 /* don't write out a null byte if the buf size is zero */ 490 *end = '\0'; 491 /* the trailing null byte doesn't count towards the total 492 * ++str; 493 */ 494 return str-buf; 495 } 496 497 EXPORT_SYMBOL(vsnprintf); 498 499 /** 500 * vscnprintf - Format a string and place it in a buffer 501 * @buf: The buffer to place the result into 502 * @size: The size of the buffer, including the trailing null space 503 * @fmt: The format string to use 504 * @args: Arguments for the format string 505 * 506 * The return value is the number of characters which have been written into 507 * the @buf not including the trailing '\0'. If @size is <= 0 the function 508 * returns 0. 509 * 510 * Call this function if you are already dealing with a va_list. 511 * You probably want scnprintf instead. 512 */ 513 int vscnprintf(char *buf, size_t size, const char *fmt, va_list args) 514 { 515 int i; 516 517 i=vsnprintf(buf,size,fmt,args); 518 return (i >= size) ? (size - 1) : i; 519 } 520 521 EXPORT_SYMBOL(vscnprintf); 522 523 /** 524 * snprintf - Format a string and place it in a buffer 525 * @buf: The buffer to place the result into 526 * @size: The size of the buffer, including the trailing null space 527 * @fmt: The format string to use 528 * @...: Arguments for the format string 529 * 530 * The return value is the number of characters which would be 531 * generated for the given input, excluding the trailing null, 532 * as per ISO C99. If the return is greater than or equal to 533 * @size, the resulting string is truncated. 534 */ 535 int snprintf(char * buf, size_t size, const char *fmt, ...) 536 { 537 va_list args; 538 int i; 539 540 va_start(args, fmt); 541 i=vsnprintf(buf,size,fmt,args); 542 va_end(args); 543 return i; 544 } 545 546 EXPORT_SYMBOL(snprintf); 547 548 /** 549 * scnprintf - Format a string and place it in a buffer 550 * @buf: The buffer to place the result into 551 * @size: The size of the buffer, including the trailing null space 552 * @fmt: The format string to use 553 * @...: Arguments for the format string 554 * 555 * The return value is the number of characters written into @buf not including 556 * the trailing '\0'. If @size is <= 0 the function returns 0. If the return is 557 * greater than or equal to @size, the resulting string is truncated. 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