Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
[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/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);