Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[linux-2.6] / lib / vsprintf.c
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);