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