11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * linux/lib/vsprintf.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds 51da177e4SLinus Torvalds */ 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ 81da177e4SLinus Torvalds /* 91da177e4SLinus Torvalds * Wirzenius wrote this portably, Torvalds fucked it up :-) 101da177e4SLinus Torvalds */ 111da177e4SLinus Torvalds 121da177e4SLinus Torvalds /* 131da177e4SLinus Torvalds * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com> 141da177e4SLinus Torvalds * - changed to provide snprintf and vsnprintf functions 151da177e4SLinus Torvalds * So Feb 1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de> 161da177e4SLinus Torvalds * - scnprintf and vscnprintf 171da177e4SLinus Torvalds */ 181da177e4SLinus Torvalds 191da177e4SLinus Torvalds #include <stdarg.h> 201da177e4SLinus Torvalds #include <linux/module.h> 211da177e4SLinus Torvalds #include <linux/types.h> 221da177e4SLinus Torvalds #include <linux/string.h> 231da177e4SLinus Torvalds #include <linux/ctype.h> 241da177e4SLinus Torvalds #include <linux/kernel.h> 251da177e4SLinus Torvalds 26*4e57b681STim Schmielau #include <asm/page.h> /* for PAGE_SIZE */ 271da177e4SLinus Torvalds #include <asm/div64.h> 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds /** 301da177e4SLinus Torvalds * simple_strtoul - convert a string to an unsigned long 311da177e4SLinus Torvalds * @cp: The start of the string 321da177e4SLinus Torvalds * @endp: A pointer to the end of the parsed string will be placed here 331da177e4SLinus Torvalds * @base: The number base to use 341da177e4SLinus Torvalds */ 351da177e4SLinus Torvalds unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) 361da177e4SLinus Torvalds { 371da177e4SLinus Torvalds unsigned long result = 0,value; 381da177e4SLinus Torvalds 391da177e4SLinus Torvalds if (!base) { 401da177e4SLinus Torvalds base = 10; 411da177e4SLinus Torvalds if (*cp == '0') { 421da177e4SLinus Torvalds base = 8; 431da177e4SLinus Torvalds cp++; 441da177e4SLinus Torvalds if ((toupper(*cp) == 'X') && isxdigit(cp[1])) { 451da177e4SLinus Torvalds cp++; 461da177e4SLinus Torvalds base = 16; 471da177e4SLinus Torvalds } 481da177e4SLinus Torvalds } 491da177e4SLinus Torvalds } else if (base == 16) { 501da177e4SLinus Torvalds if (cp[0] == '0' && toupper(cp[1]) == 'X') 511da177e4SLinus Torvalds cp += 2; 521da177e4SLinus Torvalds } 531da177e4SLinus Torvalds while (isxdigit(*cp) && 541da177e4SLinus Torvalds (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) { 551da177e4SLinus Torvalds result = result*base + value; 561da177e4SLinus Torvalds cp++; 571da177e4SLinus Torvalds } 581da177e4SLinus Torvalds if (endp) 591da177e4SLinus Torvalds *endp = (char *)cp; 601da177e4SLinus Torvalds return result; 611da177e4SLinus Torvalds } 621da177e4SLinus Torvalds 631da177e4SLinus Torvalds EXPORT_SYMBOL(simple_strtoul); 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds /** 661da177e4SLinus Torvalds * simple_strtol - convert a string to a signed long 671da177e4SLinus Torvalds * @cp: The start of the string 681da177e4SLinus Torvalds * @endp: A pointer to the end of the parsed string will be placed here 691da177e4SLinus Torvalds * @base: The number base to use 701da177e4SLinus Torvalds */ 711da177e4SLinus Torvalds long simple_strtol(const char *cp,char **endp,unsigned int base) 721da177e4SLinus Torvalds { 731da177e4SLinus Torvalds if(*cp=='-') 741da177e4SLinus Torvalds return -simple_strtoul(cp+1,endp,base); 751da177e4SLinus Torvalds return simple_strtoul(cp,endp,base); 761da177e4SLinus Torvalds } 771da177e4SLinus Torvalds 781da177e4SLinus Torvalds EXPORT_SYMBOL(simple_strtol); 791da177e4SLinus Torvalds 801da177e4SLinus Torvalds /** 811da177e4SLinus Torvalds * simple_strtoull - convert a string to an unsigned long long 821da177e4SLinus Torvalds * @cp: The start of the string 831da177e4SLinus Torvalds * @endp: A pointer to the end of the parsed string will be placed here 841da177e4SLinus Torvalds * @base: The number base to use 851da177e4SLinus Torvalds */ 861da177e4SLinus Torvalds unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base) 871da177e4SLinus Torvalds { 881da177e4SLinus Torvalds unsigned long long result = 0,value; 891da177e4SLinus Torvalds 901da177e4SLinus Torvalds if (!base) { 911da177e4SLinus Torvalds base = 10; 921da177e4SLinus Torvalds if (*cp == '0') { 931da177e4SLinus Torvalds base = 8; 941da177e4SLinus Torvalds cp++; 951da177e4SLinus Torvalds if ((toupper(*cp) == 'X') && isxdigit(cp[1])) { 961da177e4SLinus Torvalds cp++; 971da177e4SLinus Torvalds base = 16; 981da177e4SLinus Torvalds } 991da177e4SLinus Torvalds } 1001da177e4SLinus Torvalds } else if (base == 16) { 1011da177e4SLinus Torvalds if (cp[0] == '0' && toupper(cp[1]) == 'X') 1021da177e4SLinus Torvalds cp += 2; 1031da177e4SLinus Torvalds } 1041da177e4SLinus Torvalds while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) 1051da177e4SLinus Torvalds ? toupper(*cp) : *cp)-'A'+10) < base) { 1061da177e4SLinus Torvalds result = result*base + value; 1071da177e4SLinus Torvalds cp++; 1081da177e4SLinus Torvalds } 1091da177e4SLinus Torvalds if (endp) 1101da177e4SLinus Torvalds *endp = (char *)cp; 1111da177e4SLinus Torvalds return result; 1121da177e4SLinus Torvalds } 1131da177e4SLinus Torvalds 1141da177e4SLinus Torvalds EXPORT_SYMBOL(simple_strtoull); 1151da177e4SLinus Torvalds 1161da177e4SLinus Torvalds /** 1171da177e4SLinus Torvalds * simple_strtoll - convert a string to a signed long long 1181da177e4SLinus Torvalds * @cp: The start of the string 1191da177e4SLinus Torvalds * @endp: A pointer to the end of the parsed string will be placed here 1201da177e4SLinus Torvalds * @base: The number base to use 1211da177e4SLinus Torvalds */ 1221da177e4SLinus Torvalds long long simple_strtoll(const char *cp,char **endp,unsigned int base) 1231da177e4SLinus Torvalds { 1241da177e4SLinus Torvalds if(*cp=='-') 1251da177e4SLinus Torvalds return -simple_strtoull(cp+1,endp,base); 1261da177e4SLinus Torvalds return simple_strtoull(cp,endp,base); 1271da177e4SLinus Torvalds } 1281da177e4SLinus Torvalds 1291da177e4SLinus Torvalds static int skip_atoi(const char **s) 1301da177e4SLinus Torvalds { 1311da177e4SLinus Torvalds int i=0; 1321da177e4SLinus Torvalds 1331da177e4SLinus Torvalds while (isdigit(**s)) 1341da177e4SLinus Torvalds i = i*10 + *((*s)++) - '0'; 1351da177e4SLinus Torvalds return i; 1361da177e4SLinus Torvalds } 1371da177e4SLinus Torvalds 1381da177e4SLinus Torvalds #define ZEROPAD 1 /* pad with zero */ 1391da177e4SLinus Torvalds #define SIGN 2 /* unsigned/signed long */ 1401da177e4SLinus Torvalds #define PLUS 4 /* show plus */ 1411da177e4SLinus Torvalds #define SPACE 8 /* space if plus */ 1421da177e4SLinus Torvalds #define LEFT 16 /* left justified */ 1431da177e4SLinus Torvalds #define SPECIAL 32 /* 0x */ 1441da177e4SLinus Torvalds #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ 1451da177e4SLinus Torvalds 1461da177e4SLinus Torvalds static char * number(char * buf, char * end, unsigned long long num, int base, int size, int precision, int type) 1471da177e4SLinus Torvalds { 1481da177e4SLinus Torvalds char c,sign,tmp[66]; 1491da177e4SLinus Torvalds const char *digits; 1501da177e4SLinus Torvalds static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; 1511da177e4SLinus Torvalds static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 1521da177e4SLinus Torvalds int i; 1531da177e4SLinus Torvalds 1541da177e4SLinus Torvalds digits = (type & LARGE) ? large_digits : small_digits; 1551da177e4SLinus Torvalds if (type & LEFT) 1561da177e4SLinus Torvalds type &= ~ZEROPAD; 1571da177e4SLinus Torvalds if (base < 2 || base > 36) 1581da177e4SLinus Torvalds return NULL; 1591da177e4SLinus Torvalds c = (type & ZEROPAD) ? '0' : ' '; 1601da177e4SLinus Torvalds sign = 0; 1611da177e4SLinus Torvalds if (type & SIGN) { 1621da177e4SLinus Torvalds if ((signed long long) num < 0) { 1631da177e4SLinus Torvalds sign = '-'; 1641da177e4SLinus Torvalds num = - (signed long long) num; 1651da177e4SLinus Torvalds size--; 1661da177e4SLinus Torvalds } else if (type & PLUS) { 1671da177e4SLinus Torvalds sign = '+'; 1681da177e4SLinus Torvalds size--; 1691da177e4SLinus Torvalds } else if (type & SPACE) { 1701da177e4SLinus Torvalds sign = ' '; 1711da177e4SLinus Torvalds size--; 1721da177e4SLinus Torvalds } 1731da177e4SLinus Torvalds } 1741da177e4SLinus Torvalds if (type & SPECIAL) { 1751da177e4SLinus Torvalds if (base == 16) 1761da177e4SLinus Torvalds size -= 2; 1771da177e4SLinus Torvalds else if (base == 8) 1781da177e4SLinus Torvalds size--; 1791da177e4SLinus Torvalds } 1801da177e4SLinus Torvalds i = 0; 1811da177e4SLinus Torvalds if (num == 0) 1821da177e4SLinus Torvalds tmp[i++]='0'; 1831da177e4SLinus Torvalds else while (num != 0) 1841da177e4SLinus Torvalds tmp[i++] = digits[do_div(num,base)]; 1851da177e4SLinus Torvalds if (i > precision) 1861da177e4SLinus Torvalds precision = i; 1871da177e4SLinus Torvalds size -= precision; 1881da177e4SLinus Torvalds if (!(type&(ZEROPAD+LEFT))) { 1891da177e4SLinus Torvalds while(size-->0) { 1901da177e4SLinus Torvalds if (buf <= end) 1911da177e4SLinus Torvalds *buf = ' '; 1921da177e4SLinus Torvalds ++buf; 1931da177e4SLinus Torvalds } 1941da177e4SLinus Torvalds } 1951da177e4SLinus Torvalds if (sign) { 1961da177e4SLinus Torvalds if (buf <= end) 1971da177e4SLinus Torvalds *buf = sign; 1981da177e4SLinus Torvalds ++buf; 1991da177e4SLinus Torvalds } 2001da177e4SLinus Torvalds if (type & SPECIAL) { 2011da177e4SLinus Torvalds if (base==8) { 2021da177e4SLinus Torvalds if (buf <= end) 2031da177e4SLinus Torvalds *buf = '0'; 2041da177e4SLinus Torvalds ++buf; 2051da177e4SLinus Torvalds } else if (base==16) { 2061da177e4SLinus Torvalds if (buf <= end) 2071da177e4SLinus Torvalds *buf = '0'; 2081da177e4SLinus Torvalds ++buf; 2091da177e4SLinus Torvalds if (buf <= end) 2101da177e4SLinus Torvalds *buf = digits[33]; 2111da177e4SLinus Torvalds ++buf; 2121da177e4SLinus Torvalds } 2131da177e4SLinus Torvalds } 2141da177e4SLinus Torvalds if (!(type & LEFT)) { 2151da177e4SLinus Torvalds while (size-- > 0) { 2161da177e4SLinus Torvalds if (buf <= end) 2171da177e4SLinus Torvalds *buf = c; 2181da177e4SLinus Torvalds ++buf; 2191da177e4SLinus Torvalds } 2201da177e4SLinus Torvalds } 2211da177e4SLinus Torvalds while (i < precision--) { 2221da177e4SLinus Torvalds if (buf <= end) 2231da177e4SLinus Torvalds *buf = '0'; 2241da177e4SLinus Torvalds ++buf; 2251da177e4SLinus Torvalds } 2261da177e4SLinus Torvalds while (i-- > 0) { 2271da177e4SLinus Torvalds if (buf <= end) 2281da177e4SLinus Torvalds *buf = tmp[i]; 2291da177e4SLinus Torvalds ++buf; 2301da177e4SLinus Torvalds } 2311da177e4SLinus Torvalds while (size-- > 0) { 2321da177e4SLinus Torvalds if (buf <= end) 2331da177e4SLinus Torvalds *buf = ' '; 2341da177e4SLinus Torvalds ++buf; 2351da177e4SLinus Torvalds } 2361da177e4SLinus Torvalds return buf; 2371da177e4SLinus Torvalds } 2381da177e4SLinus Torvalds 2391da177e4SLinus Torvalds /** 2401da177e4SLinus Torvalds * vsnprintf - Format a string and place it in a buffer 2411da177e4SLinus Torvalds * @buf: The buffer to place the result into 2421da177e4SLinus Torvalds * @size: The size of the buffer, including the trailing null space 2431da177e4SLinus Torvalds * @fmt: The format string to use 2441da177e4SLinus Torvalds * @args: Arguments for the format string 2451da177e4SLinus Torvalds * 2461da177e4SLinus Torvalds * The return value is the number of characters which would 2471da177e4SLinus Torvalds * be generated for the given input, excluding the trailing 2481da177e4SLinus Torvalds * '\0', as per ISO C99. If you want to have the exact 2491da177e4SLinus Torvalds * number of characters written into @buf as return value 2501da177e4SLinus Torvalds * (not including the trailing '\0'), use vscnprintf. If the 2511da177e4SLinus Torvalds * return is greater than or equal to @size, the resulting 2521da177e4SLinus Torvalds * string is truncated. 2531da177e4SLinus Torvalds * 2541da177e4SLinus Torvalds * Call this function if you are already dealing with a va_list. 2551da177e4SLinus Torvalds * You probably want snprintf instead. 2561da177e4SLinus Torvalds */ 2571da177e4SLinus Torvalds int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) 2581da177e4SLinus Torvalds { 2591da177e4SLinus Torvalds int len; 2601da177e4SLinus Torvalds unsigned long long num; 2611da177e4SLinus Torvalds int i, base; 2621da177e4SLinus Torvalds char *str, *end, c; 2631da177e4SLinus Torvalds const char *s; 2641da177e4SLinus Torvalds 2651da177e4SLinus Torvalds int flags; /* flags to number() */ 2661da177e4SLinus Torvalds 2671da177e4SLinus Torvalds int field_width; /* width of output field */ 2681da177e4SLinus Torvalds int precision; /* min. # of digits for integers; max 2691da177e4SLinus Torvalds number of chars for from string */ 2701da177e4SLinus Torvalds int qualifier; /* 'h', 'l', or 'L' for integer fields */ 2711da177e4SLinus Torvalds /* 'z' support added 23/7/1999 S.H. */ 2721da177e4SLinus Torvalds /* 'z' changed to 'Z' --davidm 1/25/99 */ 27380322306SAl Viro /* 't' added for ptrdiff_t */ 2741da177e4SLinus Torvalds 2751da177e4SLinus Torvalds /* Reject out-of-range values early */ 2761da177e4SLinus Torvalds if (unlikely((int) size < 0)) { 2771da177e4SLinus Torvalds /* There can be only one.. */ 2781da177e4SLinus Torvalds static int warn = 1; 2791da177e4SLinus Torvalds WARN_ON(warn); 2801da177e4SLinus Torvalds warn = 0; 2811da177e4SLinus Torvalds return 0; 2821da177e4SLinus Torvalds } 2831da177e4SLinus Torvalds 2841da177e4SLinus Torvalds str = buf; 2851da177e4SLinus Torvalds end = buf + size - 1; 2861da177e4SLinus Torvalds 2871da177e4SLinus Torvalds if (end < buf - 1) { 2881da177e4SLinus Torvalds end = ((void *) -1); 2891da177e4SLinus Torvalds size = end - buf + 1; 2901da177e4SLinus Torvalds } 2911da177e4SLinus Torvalds 2921da177e4SLinus Torvalds for (; *fmt ; ++fmt) { 2931da177e4SLinus Torvalds if (*fmt != '%') { 2941da177e4SLinus Torvalds if (str <= end) 2951da177e4SLinus Torvalds *str = *fmt; 2961da177e4SLinus Torvalds ++str; 2971da177e4SLinus Torvalds continue; 2981da177e4SLinus Torvalds } 2991da177e4SLinus Torvalds 3001da177e4SLinus Torvalds /* process flags */ 3011da177e4SLinus Torvalds flags = 0; 3021da177e4SLinus Torvalds repeat: 3031da177e4SLinus Torvalds ++fmt; /* this also skips first '%' */ 3041da177e4SLinus Torvalds switch (*fmt) { 3051da177e4SLinus Torvalds case '-': flags |= LEFT; goto repeat; 3061da177e4SLinus Torvalds case '+': flags |= PLUS; goto repeat; 3071da177e4SLinus Torvalds case ' ': flags |= SPACE; goto repeat; 3081da177e4SLinus Torvalds case '#': flags |= SPECIAL; goto repeat; 3091da177e4SLinus Torvalds case '0': flags |= ZEROPAD; goto repeat; 3101da177e4SLinus Torvalds } 3111da177e4SLinus Torvalds 3121da177e4SLinus Torvalds /* get field width */ 3131da177e4SLinus Torvalds field_width = -1; 3141da177e4SLinus Torvalds if (isdigit(*fmt)) 3151da177e4SLinus Torvalds field_width = skip_atoi(&fmt); 3161da177e4SLinus Torvalds else if (*fmt == '*') { 3171da177e4SLinus Torvalds ++fmt; 3181da177e4SLinus Torvalds /* it's the next argument */ 3191da177e4SLinus Torvalds field_width = va_arg(args, int); 3201da177e4SLinus Torvalds if (field_width < 0) { 3211da177e4SLinus Torvalds field_width = -field_width; 3221da177e4SLinus Torvalds flags |= LEFT; 3231da177e4SLinus Torvalds } 3241da177e4SLinus Torvalds } 3251da177e4SLinus Torvalds 3261da177e4SLinus Torvalds /* get the precision */ 3271da177e4SLinus Torvalds precision = -1; 3281da177e4SLinus Torvalds if (*fmt == '.') { 3291da177e4SLinus Torvalds ++fmt; 3301da177e4SLinus Torvalds if (isdigit(*fmt)) 3311da177e4SLinus Torvalds precision = skip_atoi(&fmt); 3321da177e4SLinus Torvalds else if (*fmt == '*') { 3331da177e4SLinus Torvalds ++fmt; 3341da177e4SLinus Torvalds /* it's the next argument */ 3351da177e4SLinus Torvalds precision = va_arg(args, int); 3361da177e4SLinus Torvalds } 3371da177e4SLinus Torvalds if (precision < 0) 3381da177e4SLinus Torvalds precision = 0; 3391da177e4SLinus Torvalds } 3401da177e4SLinus Torvalds 3411da177e4SLinus Torvalds /* get the conversion qualifier */ 3421da177e4SLinus Torvalds qualifier = -1; 3431da177e4SLinus Torvalds if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || 34480322306SAl Viro *fmt =='Z' || *fmt == 'z' || *fmt == 't') { 3451da177e4SLinus Torvalds qualifier = *fmt; 3461da177e4SLinus Torvalds ++fmt; 3471da177e4SLinus Torvalds if (qualifier == 'l' && *fmt == 'l') { 3481da177e4SLinus Torvalds qualifier = 'L'; 3491da177e4SLinus Torvalds ++fmt; 3501da177e4SLinus Torvalds } 3511da177e4SLinus Torvalds } 3521da177e4SLinus Torvalds 3531da177e4SLinus Torvalds /* default base */ 3541da177e4SLinus Torvalds base = 10; 3551da177e4SLinus Torvalds 3561da177e4SLinus Torvalds switch (*fmt) { 3571da177e4SLinus Torvalds case 'c': 3581da177e4SLinus Torvalds if (!(flags & LEFT)) { 3591da177e4SLinus Torvalds while (--field_width > 0) { 3601da177e4SLinus Torvalds if (str <= end) 3611da177e4SLinus Torvalds *str = ' '; 3621da177e4SLinus Torvalds ++str; 3631da177e4SLinus Torvalds } 3641da177e4SLinus Torvalds } 3651da177e4SLinus Torvalds c = (unsigned char) va_arg(args, int); 3661da177e4SLinus Torvalds if (str <= end) 3671da177e4SLinus Torvalds *str = c; 3681da177e4SLinus Torvalds ++str; 3691da177e4SLinus Torvalds while (--field_width > 0) { 3701da177e4SLinus Torvalds if (str <= end) 3711da177e4SLinus Torvalds *str = ' '; 3721da177e4SLinus Torvalds ++str; 3731da177e4SLinus Torvalds } 3741da177e4SLinus Torvalds continue; 3751da177e4SLinus Torvalds 3761da177e4SLinus Torvalds case 's': 3771da177e4SLinus Torvalds s = va_arg(args, char *); 3781da177e4SLinus Torvalds if ((unsigned long)s < PAGE_SIZE) 3791da177e4SLinus Torvalds s = "<NULL>"; 3801da177e4SLinus Torvalds 3811da177e4SLinus Torvalds len = strnlen(s, precision); 3821da177e4SLinus Torvalds 3831da177e4SLinus Torvalds if (!(flags & LEFT)) { 3841da177e4SLinus Torvalds while (len < field_width--) { 3851da177e4SLinus Torvalds if (str <= end) 3861da177e4SLinus Torvalds *str = ' '; 3871da177e4SLinus Torvalds ++str; 3881da177e4SLinus Torvalds } 3891da177e4SLinus Torvalds } 3901da177e4SLinus Torvalds for (i = 0; i < len; ++i) { 3911da177e4SLinus Torvalds if (str <= end) 3921da177e4SLinus Torvalds *str = *s; 3931da177e4SLinus Torvalds ++str; ++s; 3941da177e4SLinus Torvalds } 3951da177e4SLinus Torvalds while (len < field_width--) { 3961da177e4SLinus Torvalds if (str <= end) 3971da177e4SLinus Torvalds *str = ' '; 3981da177e4SLinus Torvalds ++str; 3991da177e4SLinus Torvalds } 4001da177e4SLinus Torvalds continue; 4011da177e4SLinus Torvalds 4021da177e4SLinus Torvalds case 'p': 4031da177e4SLinus Torvalds if (field_width == -1) { 4041da177e4SLinus Torvalds field_width = 2*sizeof(void *); 4051da177e4SLinus Torvalds flags |= ZEROPAD; 4061da177e4SLinus Torvalds } 4071da177e4SLinus Torvalds str = number(str, end, 4081da177e4SLinus Torvalds (unsigned long) va_arg(args, void *), 4091da177e4SLinus Torvalds 16, field_width, precision, flags); 4101da177e4SLinus Torvalds continue; 4111da177e4SLinus Torvalds 4121da177e4SLinus Torvalds 4131da177e4SLinus Torvalds case 'n': 4141da177e4SLinus Torvalds /* FIXME: 4151da177e4SLinus Torvalds * What does C99 say about the overflow case here? */ 4161da177e4SLinus Torvalds if (qualifier == 'l') { 4171da177e4SLinus Torvalds long * ip = va_arg(args, long *); 4181da177e4SLinus Torvalds *ip = (str - buf); 4191da177e4SLinus Torvalds } else if (qualifier == 'Z' || qualifier == 'z') { 4201da177e4SLinus Torvalds size_t * ip = va_arg(args, size_t *); 4211da177e4SLinus Torvalds *ip = (str - buf); 4221da177e4SLinus Torvalds } else { 4231da177e4SLinus Torvalds int * ip = va_arg(args, int *); 4241da177e4SLinus Torvalds *ip = (str - buf); 4251da177e4SLinus Torvalds } 4261da177e4SLinus Torvalds continue; 4271da177e4SLinus Torvalds 4281da177e4SLinus Torvalds case '%': 4291da177e4SLinus Torvalds if (str <= end) 4301da177e4SLinus Torvalds *str = '%'; 4311da177e4SLinus Torvalds ++str; 4321da177e4SLinus Torvalds continue; 4331da177e4SLinus Torvalds 4341da177e4SLinus Torvalds /* integer number formats - set up the flags and "break" */ 4351da177e4SLinus Torvalds case 'o': 4361da177e4SLinus Torvalds base = 8; 4371da177e4SLinus Torvalds break; 4381da177e4SLinus Torvalds 4391da177e4SLinus Torvalds case 'X': 4401da177e4SLinus Torvalds flags |= LARGE; 4411da177e4SLinus Torvalds case 'x': 4421da177e4SLinus Torvalds base = 16; 4431da177e4SLinus Torvalds break; 4441da177e4SLinus Torvalds 4451da177e4SLinus Torvalds case 'd': 4461da177e4SLinus Torvalds case 'i': 4471da177e4SLinus Torvalds flags |= SIGN; 4481da177e4SLinus Torvalds case 'u': 4491da177e4SLinus Torvalds break; 4501da177e4SLinus Torvalds 4511da177e4SLinus Torvalds default: 4521da177e4SLinus Torvalds if (str <= end) 4531da177e4SLinus Torvalds *str = '%'; 4541da177e4SLinus Torvalds ++str; 4551da177e4SLinus Torvalds if (*fmt) { 4561da177e4SLinus Torvalds if (str <= end) 4571da177e4SLinus Torvalds *str = *fmt; 4581da177e4SLinus Torvalds ++str; 4591da177e4SLinus Torvalds } else { 4601da177e4SLinus Torvalds --fmt; 4611da177e4SLinus Torvalds } 4621da177e4SLinus Torvalds continue; 4631da177e4SLinus Torvalds } 4641da177e4SLinus Torvalds if (qualifier == 'L') 4651da177e4SLinus Torvalds num = va_arg(args, long long); 4661da177e4SLinus Torvalds else if (qualifier == 'l') { 4671da177e4SLinus Torvalds num = va_arg(args, unsigned long); 4681da177e4SLinus Torvalds if (flags & SIGN) 4691da177e4SLinus Torvalds num = (signed long) num; 4701da177e4SLinus Torvalds } else if (qualifier == 'Z' || qualifier == 'z') { 4711da177e4SLinus Torvalds num = va_arg(args, size_t); 47280322306SAl Viro } else if (qualifier == 't') { 47380322306SAl Viro num = va_arg(args, ptrdiff_t); 4741da177e4SLinus Torvalds } else if (qualifier == 'h') { 4751da177e4SLinus Torvalds num = (unsigned short) va_arg(args, int); 4761da177e4SLinus Torvalds if (flags & SIGN) 4771da177e4SLinus Torvalds num = (signed short) num; 4781da177e4SLinus Torvalds } else { 4791da177e4SLinus Torvalds num = va_arg(args, unsigned int); 4801da177e4SLinus Torvalds if (flags & SIGN) 4811da177e4SLinus Torvalds num = (signed int) num; 4821da177e4SLinus Torvalds } 4831da177e4SLinus Torvalds str = number(str, end, num, base, 4841da177e4SLinus Torvalds field_width, precision, flags); 4851da177e4SLinus Torvalds } 4861da177e4SLinus Torvalds if (str <= end) 4871da177e4SLinus Torvalds *str = '\0'; 4881da177e4SLinus Torvalds else if (size > 0) 4891da177e4SLinus Torvalds /* don't write out a null byte if the buf size is zero */ 4901da177e4SLinus Torvalds *end = '\0'; 4911da177e4SLinus Torvalds /* the trailing null byte doesn't count towards the total 4921da177e4SLinus Torvalds * ++str; 4931da177e4SLinus Torvalds */ 4941da177e4SLinus Torvalds return str-buf; 4951da177e4SLinus Torvalds } 4961da177e4SLinus Torvalds 4971da177e4SLinus Torvalds EXPORT_SYMBOL(vsnprintf); 4981da177e4SLinus Torvalds 4991da177e4SLinus Torvalds /** 5001da177e4SLinus Torvalds * vscnprintf - Format a string and place it in a buffer 5011da177e4SLinus Torvalds * @buf: The buffer to place the result into 5021da177e4SLinus Torvalds * @size: The size of the buffer, including the trailing null space 5031da177e4SLinus Torvalds * @fmt: The format string to use 5041da177e4SLinus Torvalds * @args: Arguments for the format string 5051da177e4SLinus Torvalds * 5061da177e4SLinus Torvalds * The return value is the number of characters which have been written into 5071da177e4SLinus Torvalds * the @buf not including the trailing '\0'. If @size is <= 0 the function 5081da177e4SLinus Torvalds * returns 0. 5091da177e4SLinus Torvalds * 5101da177e4SLinus Torvalds * Call this function if you are already dealing with a va_list. 5111da177e4SLinus Torvalds * You probably want scnprintf instead. 5121da177e4SLinus Torvalds */ 5131da177e4SLinus Torvalds int vscnprintf(char *buf, size_t size, const char *fmt, va_list args) 5141da177e4SLinus Torvalds { 5151da177e4SLinus Torvalds int i; 5161da177e4SLinus Torvalds 5171da177e4SLinus Torvalds i=vsnprintf(buf,size,fmt,args); 5181da177e4SLinus Torvalds return (i >= size) ? (size - 1) : i; 5191da177e4SLinus Torvalds } 5201da177e4SLinus Torvalds 5211da177e4SLinus Torvalds EXPORT_SYMBOL(vscnprintf); 5221da177e4SLinus Torvalds 5231da177e4SLinus Torvalds /** 5241da177e4SLinus Torvalds * snprintf - Format a string and place it in a buffer 5251da177e4SLinus Torvalds * @buf: The buffer to place the result into 5261da177e4SLinus Torvalds * @size: The size of the buffer, including the trailing null space 5271da177e4SLinus Torvalds * @fmt: The format string to use 5281da177e4SLinus Torvalds * @...: Arguments for the format string 5291da177e4SLinus Torvalds * 5301da177e4SLinus Torvalds * The return value is the number of characters which would be 5311da177e4SLinus Torvalds * generated for the given input, excluding the trailing null, 5321da177e4SLinus Torvalds * as per ISO C99. If the return is greater than or equal to 5331da177e4SLinus Torvalds * @size, the resulting string is truncated. 5341da177e4SLinus Torvalds */ 5351da177e4SLinus Torvalds int snprintf(char * buf, size_t size, const char *fmt, ...) 5361da177e4SLinus Torvalds { 5371da177e4SLinus Torvalds va_list args; 5381da177e4SLinus Torvalds int i; 5391da177e4SLinus Torvalds 5401da177e4SLinus Torvalds va_start(args, fmt); 5411da177e4SLinus Torvalds i=vsnprintf(buf,size,fmt,args); 5421da177e4SLinus Torvalds va_end(args); 5431da177e4SLinus Torvalds return i; 5441da177e4SLinus Torvalds } 5451da177e4SLinus Torvalds 5461da177e4SLinus Torvalds EXPORT_SYMBOL(snprintf); 5471da177e4SLinus Torvalds 5481da177e4SLinus Torvalds /** 5491da177e4SLinus Torvalds * scnprintf - Format a string and place it in a buffer 5501da177e4SLinus Torvalds * @buf: The buffer to place the result into 5511da177e4SLinus Torvalds * @size: The size of the buffer, including the trailing null space 5521da177e4SLinus Torvalds * @fmt: The format string to use 5531da177e4SLinus Torvalds * @...: Arguments for the format string 5541da177e4SLinus Torvalds * 5551da177e4SLinus Torvalds * The return value is the number of characters written into @buf not including 5561da177e4SLinus Torvalds * the trailing '\0'. If @size is <= 0 the function returns 0. If the return is 5571da177e4SLinus Torvalds * greater than or equal to @size, the resulting string is truncated. 5581da177e4SLinus Torvalds */ 5591da177e4SLinus Torvalds 5601da177e4SLinus Torvalds int scnprintf(char * buf, size_t size, const char *fmt, ...) 5611da177e4SLinus Torvalds { 5621da177e4SLinus Torvalds va_list args; 5631da177e4SLinus Torvalds int i; 5641da177e4SLinus Torvalds 5651da177e4SLinus Torvalds va_start(args, fmt); 5661da177e4SLinus Torvalds i = vsnprintf(buf, size, fmt, args); 5671da177e4SLinus Torvalds va_end(args); 5681da177e4SLinus Torvalds return (i >= size) ? (size - 1) : i; 5691da177e4SLinus Torvalds } 5701da177e4SLinus Torvalds EXPORT_SYMBOL(scnprintf); 5711da177e4SLinus Torvalds 5721da177e4SLinus Torvalds /** 5731da177e4SLinus Torvalds * vsprintf - Format a string and place it in a buffer 5741da177e4SLinus Torvalds * @buf: The buffer to place the result into 5751da177e4SLinus Torvalds * @fmt: The format string to use 5761da177e4SLinus Torvalds * @args: Arguments for the format string 5771da177e4SLinus Torvalds * 5781da177e4SLinus Torvalds * The function returns the number of characters written 5791da177e4SLinus Torvalds * into @buf. Use vsnprintf or vscnprintf in order to avoid 5801da177e4SLinus Torvalds * buffer overflows. 5811da177e4SLinus Torvalds * 5821da177e4SLinus Torvalds * Call this function if you are already dealing with a va_list. 5831da177e4SLinus Torvalds * You probably want sprintf instead. 5841da177e4SLinus Torvalds */ 5851da177e4SLinus Torvalds int vsprintf(char *buf, const char *fmt, va_list args) 5861da177e4SLinus Torvalds { 5871da177e4SLinus Torvalds return vsnprintf(buf, INT_MAX, fmt, args); 5881da177e4SLinus Torvalds } 5891da177e4SLinus Torvalds 5901da177e4SLinus Torvalds EXPORT_SYMBOL(vsprintf); 5911da177e4SLinus Torvalds 5921da177e4SLinus Torvalds /** 5931da177e4SLinus Torvalds * sprintf - Format a string and place it in a buffer 5941da177e4SLinus Torvalds * @buf: The buffer to place the result into 5951da177e4SLinus Torvalds * @fmt: The format string to use 5961da177e4SLinus Torvalds * @...: Arguments for the format string 5971da177e4SLinus Torvalds * 5981da177e4SLinus Torvalds * The function returns the number of characters written 5991da177e4SLinus Torvalds * into @buf. Use snprintf or scnprintf in order to avoid 6001da177e4SLinus Torvalds * buffer overflows. 6011da177e4SLinus Torvalds */ 6021da177e4SLinus Torvalds int sprintf(char * buf, const char *fmt, ...) 6031da177e4SLinus Torvalds { 6041da177e4SLinus Torvalds va_list args; 6051da177e4SLinus Torvalds int i; 6061da177e4SLinus Torvalds 6071da177e4SLinus Torvalds va_start(args, fmt); 6081da177e4SLinus Torvalds i=vsnprintf(buf, INT_MAX, fmt, args); 6091da177e4SLinus Torvalds va_end(args); 6101da177e4SLinus Torvalds return i; 6111da177e4SLinus Torvalds } 6121da177e4SLinus Torvalds 6131da177e4SLinus Torvalds EXPORT_SYMBOL(sprintf); 6141da177e4SLinus Torvalds 6151da177e4SLinus Torvalds /** 6161da177e4SLinus Torvalds * vsscanf - Unformat a buffer into a list of arguments 6171da177e4SLinus Torvalds * @buf: input buffer 6181da177e4SLinus Torvalds * @fmt: format of buffer 6191da177e4SLinus Torvalds * @args: arguments 6201da177e4SLinus Torvalds */ 6211da177e4SLinus Torvalds int vsscanf(const char * buf, const char * fmt, va_list args) 6221da177e4SLinus Torvalds { 6231da177e4SLinus Torvalds const char *str = buf; 6241da177e4SLinus Torvalds char *next; 6251da177e4SLinus Torvalds char digit; 6261da177e4SLinus Torvalds int num = 0; 6271da177e4SLinus Torvalds int qualifier; 6281da177e4SLinus Torvalds int base; 6291da177e4SLinus Torvalds int field_width; 6301da177e4SLinus Torvalds int is_sign = 0; 6311da177e4SLinus Torvalds 6321da177e4SLinus Torvalds while(*fmt && *str) { 6331da177e4SLinus Torvalds /* skip any white space in format */ 6341da177e4SLinus Torvalds /* white space in format matchs any amount of 6351da177e4SLinus Torvalds * white space, including none, in the input. 6361da177e4SLinus Torvalds */ 6371da177e4SLinus Torvalds if (isspace(*fmt)) { 6381da177e4SLinus Torvalds while (isspace(*fmt)) 6391da177e4SLinus Torvalds ++fmt; 6401da177e4SLinus Torvalds while (isspace(*str)) 6411da177e4SLinus Torvalds ++str; 6421da177e4SLinus Torvalds } 6431da177e4SLinus Torvalds 6441da177e4SLinus Torvalds /* anything that is not a conversion must match exactly */ 6451da177e4SLinus Torvalds if (*fmt != '%' && *fmt) { 6461da177e4SLinus Torvalds if (*fmt++ != *str++) 6471da177e4SLinus Torvalds break; 6481da177e4SLinus Torvalds continue; 6491da177e4SLinus Torvalds } 6501da177e4SLinus Torvalds 6511da177e4SLinus Torvalds if (!*fmt) 6521da177e4SLinus Torvalds break; 6531da177e4SLinus Torvalds ++fmt; 6541da177e4SLinus Torvalds 6551da177e4SLinus Torvalds /* skip this conversion. 6561da177e4SLinus Torvalds * advance both strings to next white space 6571da177e4SLinus Torvalds */ 6581da177e4SLinus Torvalds if (*fmt == '*') { 6591da177e4SLinus Torvalds while (!isspace(*fmt) && *fmt) 6601da177e4SLinus Torvalds fmt++; 6611da177e4SLinus Torvalds while (!isspace(*str) && *str) 6621da177e4SLinus Torvalds str++; 6631da177e4SLinus Torvalds continue; 6641da177e4SLinus Torvalds } 6651da177e4SLinus Torvalds 6661da177e4SLinus Torvalds /* get field width */ 6671da177e4SLinus Torvalds field_width = -1; 6681da177e4SLinus Torvalds if (isdigit(*fmt)) 6691da177e4SLinus Torvalds field_width = skip_atoi(&fmt); 6701da177e4SLinus Torvalds 6711da177e4SLinus Torvalds /* get conversion qualifier */ 6721da177e4SLinus Torvalds qualifier = -1; 6731da177e4SLinus Torvalds if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || 6741da177e4SLinus Torvalds *fmt == 'Z' || *fmt == 'z') { 6751da177e4SLinus Torvalds qualifier = *fmt++; 6761da177e4SLinus Torvalds if (unlikely(qualifier == *fmt)) { 6771da177e4SLinus Torvalds if (qualifier == 'h') { 6781da177e4SLinus Torvalds qualifier = 'H'; 6791da177e4SLinus Torvalds fmt++; 6801da177e4SLinus Torvalds } else if (qualifier == 'l') { 6811da177e4SLinus Torvalds qualifier = 'L'; 6821da177e4SLinus Torvalds fmt++; 6831da177e4SLinus Torvalds } 6841da177e4SLinus Torvalds } 6851da177e4SLinus Torvalds } 6861da177e4SLinus Torvalds base = 10; 6871da177e4SLinus Torvalds is_sign = 0; 6881da177e4SLinus Torvalds 6891da177e4SLinus Torvalds if (!*fmt || !*str) 6901da177e4SLinus Torvalds break; 6911da177e4SLinus Torvalds 6921da177e4SLinus Torvalds switch(*fmt++) { 6931da177e4SLinus Torvalds case 'c': 6941da177e4SLinus Torvalds { 6951da177e4SLinus Torvalds char *s = (char *) va_arg(args,char*); 6961da177e4SLinus Torvalds if (field_width == -1) 6971da177e4SLinus Torvalds field_width = 1; 6981da177e4SLinus Torvalds do { 6991da177e4SLinus Torvalds *s++ = *str++; 7001da177e4SLinus Torvalds } while (--field_width > 0 && *str); 7011da177e4SLinus Torvalds num++; 7021da177e4SLinus Torvalds } 7031da177e4SLinus Torvalds continue; 7041da177e4SLinus Torvalds case 's': 7051da177e4SLinus Torvalds { 7061da177e4SLinus Torvalds char *s = (char *) va_arg(args, char *); 7071da177e4SLinus Torvalds if(field_width == -1) 7081da177e4SLinus Torvalds field_width = INT_MAX; 7091da177e4SLinus Torvalds /* first, skip leading white space in buffer */ 7101da177e4SLinus Torvalds while (isspace(*str)) 7111da177e4SLinus Torvalds str++; 7121da177e4SLinus Torvalds 7131da177e4SLinus Torvalds /* now copy until next white space */ 7141da177e4SLinus Torvalds while (*str && !isspace(*str) && field_width--) { 7151da177e4SLinus Torvalds *s++ = *str++; 7161da177e4SLinus Torvalds } 7171da177e4SLinus Torvalds *s = '\0'; 7181da177e4SLinus Torvalds num++; 7191da177e4SLinus Torvalds } 7201da177e4SLinus Torvalds continue; 7211da177e4SLinus Torvalds case 'n': 7221da177e4SLinus Torvalds /* return number of characters read so far */ 7231da177e4SLinus Torvalds { 7241da177e4SLinus Torvalds int *i = (int *)va_arg(args,int*); 7251da177e4SLinus Torvalds *i = str - buf; 7261da177e4SLinus Torvalds } 7271da177e4SLinus Torvalds continue; 7281da177e4SLinus Torvalds case 'o': 7291da177e4SLinus Torvalds base = 8; 7301da177e4SLinus Torvalds break; 7311da177e4SLinus Torvalds case 'x': 7321da177e4SLinus Torvalds case 'X': 7331da177e4SLinus Torvalds base = 16; 7341da177e4SLinus Torvalds break; 7351da177e4SLinus Torvalds case 'i': 7361da177e4SLinus Torvalds base = 0; 7371da177e4SLinus Torvalds case 'd': 7381da177e4SLinus Torvalds is_sign = 1; 7391da177e4SLinus Torvalds case 'u': 7401da177e4SLinus Torvalds break; 7411da177e4SLinus Torvalds case '%': 7421da177e4SLinus Torvalds /* looking for '%' in str */ 7431da177e4SLinus Torvalds if (*str++ != '%') 7441da177e4SLinus Torvalds return num; 7451da177e4SLinus Torvalds continue; 7461da177e4SLinus Torvalds default: 7471da177e4SLinus Torvalds /* invalid format; stop here */ 7481da177e4SLinus Torvalds return num; 7491da177e4SLinus Torvalds } 7501da177e4SLinus Torvalds 7511da177e4SLinus Torvalds /* have some sort of integer conversion. 7521da177e4SLinus Torvalds * first, skip white space in buffer. 7531da177e4SLinus Torvalds */ 7541da177e4SLinus Torvalds while (isspace(*str)) 7551da177e4SLinus Torvalds str++; 7561da177e4SLinus Torvalds 7571da177e4SLinus Torvalds digit = *str; 7581da177e4SLinus Torvalds if (is_sign && digit == '-') 7591da177e4SLinus Torvalds digit = *(str + 1); 7601da177e4SLinus Torvalds 7611da177e4SLinus Torvalds if (!digit 7621da177e4SLinus Torvalds || (base == 16 && !isxdigit(digit)) 7631da177e4SLinus Torvalds || (base == 10 && !isdigit(digit)) 7641da177e4SLinus Torvalds || (base == 8 && (!isdigit(digit) || digit > '7')) 7651da177e4SLinus Torvalds || (base == 0 && !isdigit(digit))) 7661da177e4SLinus Torvalds break; 7671da177e4SLinus Torvalds 7681da177e4SLinus Torvalds switch(qualifier) { 7691da177e4SLinus Torvalds case 'H': /* that's 'hh' in format */ 7701da177e4SLinus Torvalds if (is_sign) { 7711da177e4SLinus Torvalds signed char *s = (signed char *) va_arg(args,signed char *); 7721da177e4SLinus Torvalds *s = (signed char) simple_strtol(str,&next,base); 7731da177e4SLinus Torvalds } else { 7741da177e4SLinus Torvalds unsigned char *s = (unsigned char *) va_arg(args, unsigned char *); 7751da177e4SLinus Torvalds *s = (unsigned char) simple_strtoul(str, &next, base); 7761da177e4SLinus Torvalds } 7771da177e4SLinus Torvalds break; 7781da177e4SLinus Torvalds case 'h': 7791da177e4SLinus Torvalds if (is_sign) { 7801da177e4SLinus Torvalds short *s = (short *) va_arg(args,short *); 7811da177e4SLinus Torvalds *s = (short) simple_strtol(str,&next,base); 7821da177e4SLinus Torvalds } else { 7831da177e4SLinus Torvalds unsigned short *s = (unsigned short *) va_arg(args, unsigned short *); 7841da177e4SLinus Torvalds *s = (unsigned short) simple_strtoul(str, &next, base); 7851da177e4SLinus Torvalds } 7861da177e4SLinus Torvalds break; 7871da177e4SLinus Torvalds case 'l': 7881da177e4SLinus Torvalds if (is_sign) { 7891da177e4SLinus Torvalds long *l = (long *) va_arg(args,long *); 7901da177e4SLinus Torvalds *l = simple_strtol(str,&next,base); 7911da177e4SLinus Torvalds } else { 7921da177e4SLinus Torvalds unsigned long *l = (unsigned long*) va_arg(args,unsigned long*); 7931da177e4SLinus Torvalds *l = simple_strtoul(str,&next,base); 7941da177e4SLinus Torvalds } 7951da177e4SLinus Torvalds break; 7961da177e4SLinus Torvalds case 'L': 7971da177e4SLinus Torvalds if (is_sign) { 7981da177e4SLinus Torvalds long long *l = (long long*) va_arg(args,long long *); 7991da177e4SLinus Torvalds *l = simple_strtoll(str,&next,base); 8001da177e4SLinus Torvalds } else { 8011da177e4SLinus Torvalds unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*); 8021da177e4SLinus Torvalds *l = simple_strtoull(str,&next,base); 8031da177e4SLinus Torvalds } 8041da177e4SLinus Torvalds break; 8051da177e4SLinus Torvalds case 'Z': 8061da177e4SLinus Torvalds case 'z': 8071da177e4SLinus Torvalds { 8081da177e4SLinus Torvalds size_t *s = (size_t*) va_arg(args,size_t*); 8091da177e4SLinus Torvalds *s = (size_t) simple_strtoul(str,&next,base); 8101da177e4SLinus Torvalds } 8111da177e4SLinus Torvalds break; 8121da177e4SLinus Torvalds default: 8131da177e4SLinus Torvalds if (is_sign) { 8141da177e4SLinus Torvalds int *i = (int *) va_arg(args, int*); 8151da177e4SLinus Torvalds *i = (int) simple_strtol(str,&next,base); 8161da177e4SLinus Torvalds } else { 8171da177e4SLinus Torvalds unsigned int *i = (unsigned int*) va_arg(args, unsigned int*); 8181da177e4SLinus Torvalds *i = (unsigned int) simple_strtoul(str,&next,base); 8191da177e4SLinus Torvalds } 8201da177e4SLinus Torvalds break; 8211da177e4SLinus Torvalds } 8221da177e4SLinus Torvalds num++; 8231da177e4SLinus Torvalds 8241da177e4SLinus Torvalds if (!next) 8251da177e4SLinus Torvalds break; 8261da177e4SLinus Torvalds str = next; 8271da177e4SLinus Torvalds } 8281da177e4SLinus Torvalds return num; 8291da177e4SLinus Torvalds } 8301da177e4SLinus Torvalds 8311da177e4SLinus Torvalds EXPORT_SYMBOL(vsscanf); 8321da177e4SLinus Torvalds 8331da177e4SLinus Torvalds /** 8341da177e4SLinus Torvalds * sscanf - Unformat a buffer into a list of arguments 8351da177e4SLinus Torvalds * @buf: input buffer 8361da177e4SLinus Torvalds * @fmt: formatting of buffer 8371da177e4SLinus Torvalds * @...: resulting arguments 8381da177e4SLinus Torvalds */ 8391da177e4SLinus Torvalds int sscanf(const char * buf, const char * fmt, ...) 8401da177e4SLinus Torvalds { 8411da177e4SLinus Torvalds va_list args; 8421da177e4SLinus Torvalds int i; 8431da177e4SLinus Torvalds 8441da177e4SLinus Torvalds va_start(args,fmt); 8451da177e4SLinus Torvalds i = vsscanf(buf,fmt,args); 8461da177e4SLinus Torvalds va_end(args); 8471da177e4SLinus Torvalds return i; 8481da177e4SLinus Torvalds } 8491da177e4SLinus Torvalds 8501da177e4SLinus Torvalds EXPORT_SYMBOL(sscanf); 851