Linux-2.6.12-rc2
[linux-2.6.git] / 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
273         /* Reject out-of-range values early */
274         if (unlikely((int) size < 0)) {
275                 /* There can be only one.. */
276                 static int warn = 1;
277                 WARN_ON(warn);
278                 warn = 0;
279                 return 0;
280         }
281
282         str = buf;
283         end = buf + size - 1;
284
285         if (end < buf - 1) {
286                 end = ((void *) -1);
287                 size = end - buf + 1;
288         }
289
290         for (; *fmt ; ++fmt) {
291                 if (*fmt != '%') {
292                         if (str <= end)
293                                 *str = *fmt;
294                         ++str;
295                         continue;
296                 }
297
298                 /* process flags */
299                 flags = 0;
300                 repeat:
301                         ++fmt;          /* this also skips first '%' */
302                         switch (*fmt) {
303                                 case '-': flags |= LEFT; goto repeat;
304                                 case '+': flags |= PLUS; goto repeat;
305                                 case ' ': flags |= SPACE; goto repeat;
306                                 case '#': flags |= SPECIAL; goto repeat;
307                                 case '0': flags |= ZEROPAD; goto repeat;
308                         }
309
310                 /* get field width */
311                 field_width = -1;
312                 if (isdigit(*fmt))
313                         field_width = skip_atoi(&fmt);
314                 else if (*fmt == '*') {
315                         ++fmt;
316                         /* it's the next argument */
317                         field_width = va_arg(args, int);
318                         if (field_width < 0) {
319                                 field_width = -field_width;
320                                 flags |= LEFT;
321                         }
322                 }
323
324                 /* get the precision */
325                 precision = -1;
326                 if (*fmt == '.') {
327                         ++fmt;  
328                         if (isdigit(*fmt))
329                                 precision = skip_atoi(&fmt);
330                         else if (*fmt == '*') {
331                                 ++fmt;
332                                 /* it's the next argument */
333                                 precision = va_arg(args, int);
334                         }
335                         if (precision < 0)
336                                 precision = 0;
337                 }
338
339                 /* get the conversion qualifier */
340                 qualifier = -1;
341                 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
342                     *fmt =='Z' || *fmt == 'z') {
343                         qualifier = *fmt;
344                         ++fmt;
345                         if (qualifier == 'l' && *fmt == 'l') {
346                                 qualifier = 'L';
347                                 ++fmt;
348                         }
349                 }
350
351                 /* default base */
352                 base = 10;
353
354                 switch (*fmt) {
355                         case 'c':
356                                 if (!(flags & LEFT)) {
357                                         while (--field_width > 0) {
358                                                 if (str <= end)
359                                                         *str = ' ';
360                                                 ++str;
361                                         }
362                                 }
363                                 c = (unsigned char) va_arg(args, int);
364                                 if (str <= end)
365                                         *str = c;
366                                 ++str;
367                                 while (--field_width > 0) {
368                                         if (str <= end)
369                                                 *str = ' ';
370                                         ++str;
371                                 }
372                                 continue;
373
374                         case 's':
375                                 s = va_arg(args, char *);
376                                 if ((unsigned long)s < PAGE_SIZE)
377                                         s = "<NULL>";
378
379                                 len = strnlen(s, precision);
380
381                                 if (!(flags & LEFT)) {
382                                         while (len < field_width--) {
383                                                 if (str <= end)
384                                                         *str = ' ';
385                                                 ++str;
386                                         }
387                                 }
388                                 for (i = 0; i < len; ++i) {
389                                         if (str <= end)
390                                                 *str = *s;
391                                         ++str; ++s;
392                                 }
393                                 while (len < field_width--) {
394                                         if (str <= end)
395                                                 *str = ' ';
396                                         ++str;
397                                 }
398                                 continue;
399
400                         case 'p':
401                                 if (field_width == -1) {
402                                         field_width = 2*sizeof(void *);
403                                         flags |= ZEROPAD;
404                                 }
405                                 str = number(str, end,
406                                                 (unsigned long) va_arg(args, void *),
407                                                 16, field_width, precision, flags);
408                                 continue;
409
410
411                         case 'n':
412                                 /* FIXME:
413                                 * What does C99 say about the overflow case here? */
414                                 if (qualifier == 'l') {
415                                         long * ip = va_arg(args, long *);
416                                         *ip = (str - buf);
417                                 } else if (qualifier == 'Z' || qualifier == 'z') {
418                                         size_t * ip = va_arg(args, size_t *);
419                                         *ip = (str - buf);
420                                 } else {
421                                         int * ip = va_arg(args, int *);
422                                         *ip = (str - buf);
423                                 }
424                                 continue;
425
426                         case '%':
427                                 if (str <= end)
428                                         *str = '%';
429                                 ++str;
430                                 continue;
431
432                                 /* integer number formats - set up the flags and "break" */
433                         case 'o':
434                                 base = 8;
435                                 break;
436
437                         case 'X':
438                                 flags |= LARGE;
439                         case 'x':
440                                 base = 16;
441                                 break;
442
443                         case 'd':
444                         case 'i':
445                                 flags |= SIGN;
446                         case 'u':
447                                 break;
448
449                         default:
450                                 if (str <= end)
451                                         *str = '%';
452                                 ++str;
453                                 if (*fmt) {
454                                         if (str <= end)
455                                                 *str = *fmt;
456                                         ++str;
457                                 } else {
458                                         --fmt;
459                                 }
460                                 continue;
461                 }
462                 if (qualifier == 'L')
463                         num = va_arg(args, long long);
464                 else if (qualifier == 'l') {
465                         num = va_arg(args, unsigned long);
466                         if (flags & SIGN)
467                                 num = (signed long) num;
468                 } else if (qualifier == 'Z' || qualifier == 'z') {
469                         num = va_arg(args, size_t);
470                 } else if (qualifier == 'h') {
471                         num = (unsigned short) va_arg(args, int);
472                         if (flags & SIGN)
473                                 num = (signed short) num;
474                 } else {
475                         num = va_arg(args, unsigned int);
476                         if (flags & SIGN)
477                                 num = (signed int) num;
478                 }
479                 str = number(str, end, num, base,
480                                 field_width, precision, flags);
481         }
482         if (str <= end)
483                 *str = '\0';
484         else if (size > 0)
485                 /* don't write out a null byte if the buf size is zero */
486                 *end = '\0';
487         /* the trailing null byte doesn't count towards the total
488         * ++str;
489         */
490         return str-buf;
491 }
492
493 EXPORT_SYMBOL(vsnprintf);
494
495 /**
496  * vscnprintf - Format a string and place it in a buffer
497  * @buf: The buffer to place the result into
498  * @size: The size of the buffer, including the trailing null space
499  * @fmt: The format string to use
500  * @args: Arguments for the format string
501  *
502  * The return value is the number of characters which have been written into
503  * the @buf not including the trailing '\0'. If @size is <= 0 the function
504  * returns 0.
505  *
506  * Call this function if you are already dealing with a va_list.
507  * You probably want scnprintf instead.
508  */
509 int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
510 {
511         int i;
512
513         i=vsnprintf(buf,size,fmt,args);
514         return (i >= size) ? (size - 1) : i;
515 }
516
517 EXPORT_SYMBOL(vscnprintf);
518
519 /**
520  * snprintf - Format a string and place it in a buffer
521  * @buf: The buffer to place the result into
522  * @size: The size of the buffer, including the trailing null space
523  * @fmt: The format string to use
524  * @...: Arguments for the format string
525  *
526  * The return value is the number of characters which would be
527  * generated for the given input, excluding the trailing null,
528  * as per ISO C99.  If the return is greater than or equal to
529  * @size, the resulting string is truncated.
530  */
531 int snprintf(char * buf, size_t size, const char *fmt, ...)
532 {
533         va_list args;
534         int i;
535
536         va_start(args, fmt);
537         i=vsnprintf(buf,size,fmt,args);
538         va_end(args);
539         return i;
540 }
541
542 EXPORT_SYMBOL(snprintf);
543
544 /**
545  * scnprintf - Format a string and place it in a buffer
546  * @buf: The buffer to place the result into
547  * @size: The size of the buffer, including the trailing null space
548  * @fmt: The format string to use
549  * @...: Arguments for the format string
550  *
551  * The return value is the number of characters written into @buf not including
552  * the trailing '\0'. If @size is <= 0 the function returns 0. If the return is
553  * greater than or equal to @size, the resulting string is truncated.
554  */
555
556 int scnprintf(char * buf, size_t size, const char *fmt, ...)
557 {
558         va_list args;
559         int i;
560
561         va_start(args, fmt);
562         i = vsnprintf(buf, size, fmt, args);
563         va_end(args);
564         return (i >= size) ? (size - 1) : i;
565 }
566 EXPORT_SYMBOL(scnprintf);
567
568 /**
569  * vsprintf - Format a string and place it in a buffer
570  * @buf: The buffer to place the result into
571  * @fmt: The format string to use
572  * @args: Arguments for the format string
573  *
574  * The function returns the number of characters written
575  * into @buf. Use vsnprintf or vscnprintf in order to avoid
576  * buffer overflows.
577  *
578  * Call this function if you are already dealing with a va_list.
579  * You probably want sprintf instead.
580  */
581 int vsprintf(char *buf, const char *fmt, va_list args)
582 {
583         return vsnprintf(buf, INT_MAX, fmt, args);
584 }
585
586 EXPORT_SYMBOL(vsprintf);
587
588 /**
589  * sprintf - Format a string and place it in a buffer
590  * @buf: The buffer to place the result into
591  * @fmt: The format string to use
592  * @...: Arguments for the format string
593  *
594  * The function returns the number of characters written
595  * into @buf. Use snprintf or scnprintf in order to avoid
596  * buffer overflows.
597  */
598 int sprintf(char * buf, const char *fmt, ...)
599 {
600         va_list args;
601         int i;
602
603         va_start(args, fmt);
604         i=vsnprintf(buf, INT_MAX, fmt, args);
605         va_end(args);
606         return i;
607 }
608
609 EXPORT_SYMBOL(sprintf);
610
611 /**
612  * vsscanf - Unformat a buffer into a list of arguments
613  * @buf:        input buffer
614  * @fmt:        format of buffer
615  * @args:       arguments
616  */
617 int vsscanf(const char * buf, const char * fmt, va_list args)
618 {
619         const char *str = buf;
620         char *next;
621         char digit;
622         int num = 0;
623         int qualifier;
624         int base;
625         int field_width;
626         int is_sign = 0;
627
628         while(*fmt && *str) {
629                 /* skip any white space in format */
630                 /* white space in format matchs any amount of
631                  * white space, including none, in the input.
632                  */
633                 if (isspace(*fmt)) {
634                         while (isspace(*fmt))
635                                 ++fmt;
636                         while (isspace(*str))
637                                 ++str;
638                 }
639
640                 /* anything that is not a conversion must match exactly */
641                 if (*fmt != '%' && *fmt) {
642                         if (*fmt++ != *str++)
643                                 break;
644                         continue;
645                 }
646
647                 if (!*fmt)
648                         break;
649                 ++fmt;
650                 
651                 /* skip this conversion.
652                  * advance both strings to next white space
653                  */
654                 if (*fmt == '*') {
655                         while (!isspace(*fmt) && *fmt)
656                                 fmt++;
657                         while (!isspace(*str) && *str)
658                                 str++;
659                         continue;
660                 }
661
662                 /* get field width */
663                 field_width = -1;
664                 if (isdigit(*fmt))
665                         field_width = skip_atoi(&fmt);
666
667                 /* get conversion qualifier */
668                 qualifier = -1;
669                 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
670                     *fmt == 'Z' || *fmt == 'z') {
671                         qualifier = *fmt++;
672                         if (unlikely(qualifier == *fmt)) {
673                                 if (qualifier == 'h') {
674                                         qualifier = 'H';
675                                         fmt++;
676                                 } else if (qualifier == 'l') {
677                                         qualifier = 'L';
678                                         fmt++;
679                                 }
680                         }
681                 }
682                 base = 10;
683                 is_sign = 0;
684
685                 if (!*fmt || !*str)
686                         break;
687
688                 switch(*fmt++) {
689                 case 'c':
690                 {
691                         char *s = (char *) va_arg(args,char*);
692                         if (field_width == -1)
693                                 field_width = 1;
694                         do {
695                                 *s++ = *str++;
696                         } while (--field_width > 0 && *str);
697                         num++;
698                 }
699                 continue;
700                 case 's':
701                 {
702                         char *s = (char *) va_arg(args, char *);
703                         if(field_width == -1)
704                                 field_width = INT_MAX;
705                         /* first, skip leading white space in buffer */
706                         while (isspace(*str))
707                                 str++;
708
709                         /* now copy until next white space */
710                         while (*str && !isspace(*str) && field_width--) {
711                                 *s++ = *str++;
712                         }
713                         *s = '\0';
714                         num++;
715                 }
716                 continue;
717                 case 'n':
718                         /* return number of characters read so far */
719                 {
720                         int *i = (int *)va_arg(args,int*);
721                         *i = str - buf;
722                 }
723                 continue;
724                 case 'o':
725                         base = 8;
726                         break;
727                 case 'x':
728                 case 'X':
729                         base = 16;
730                         break;
731                 case 'i':
732                         base = 0;
733                 case 'd':
734                         is_sign = 1;
735                 case 'u':
736                         break;
737                 case '%':
738                         /* looking for '%' in str */
739                         if (*str++ != '%') 
740                                 return num;
741                         continue;
742                 default:
743                         /* invalid format; stop here */
744                         return num;
745                 }
746
747                 /* have some sort of integer conversion.
748                  * first, skip white space in buffer.
749                  */
750                 while (isspace(*str))
751                         str++;
752
753                 digit = *str;
754                 if (is_sign && digit == '-')
755                         digit = *(str + 1);
756
757                 if (!digit
758                     || (base == 16 && !isxdigit(digit))
759                     || (base == 10 && !isdigit(digit))
760                     || (base == 8 && (!isdigit(digit) || digit > '7'))
761                     || (base == 0 && !isdigit(digit)))
762                                 break;
763
764                 switch(qualifier) {
765                 case 'H':       /* that's 'hh' in format */
766                         if (is_sign) {
767                                 signed char *s = (signed char *) va_arg(args,signed char *);
768                                 *s = (signed char) simple_strtol(str,&next,base);
769                         } else {
770                                 unsigned char *s = (unsigned char *) va_arg(args, unsigned char *);
771                                 *s = (unsigned char) simple_strtoul(str, &next, base);
772                         }
773                         break;
774                 case 'h':
775                         if (is_sign) {
776                                 short *s = (short *) va_arg(args,short *);
777                                 *s = (short) simple_strtol(str,&next,base);
778                         } else {
779                                 unsigned short *s = (unsigned short *) va_arg(args, unsigned short *);
780                                 *s = (unsigned short) simple_strtoul(str, &next, base);
781                         }
782                         break;
783                 case 'l':
784                         if (is_sign) {
785                                 long *l = (long *) va_arg(args,long *);
786                                 *l = simple_strtol(str,&next,base);
787                         } else {
788                                 unsigned long *l = (unsigned long*) va_arg(args,unsigned long*);
789                                 *l = simple_strtoul(str,&next,base);
790                         }
791                         break;
792                 case 'L':
793                         if (is_sign) {
794                                 long long *l = (long long*) va_arg(args,long long *);
795                                 *l = simple_strtoll(str,&next,base);
796                         } else {
797                                 unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*);
798                                 *l = simple_strtoull(str,&next,base);
799                         }
800                         break;
801                 case 'Z':
802                 case 'z':
803                 {
804                         size_t *s = (size_t*) va_arg(args,size_t*);
805                         *s = (size_t) simple_strtoul(str,&next,base);
806                 }
807                 break;
808                 default:
809                         if (is_sign) {
810                                 int *i = (int *) va_arg(args, int*);
811                                 *i = (int) simple_strtol(str,&next,base);
812                         } else {
813                                 unsigned int *i = (unsigned int*) va_arg(args, unsigned int*);
814                                 *i = (unsigned int) simple_strtoul(str,&next,base);
815                         }
816                         break;
817                 }
818                 num++;
819
820                 if (!next)
821                         break;
822                 str = next;
823         }
824         return num;
825 }
826
827 EXPORT_SYMBOL(vsscanf);
828
829 /**
830  * sscanf - Unformat a buffer into a list of arguments
831  * @buf:        input buffer
832  * @fmt:        formatting of buffer
833  * @...:        resulting arguments
834  */
835 int sscanf(const char * buf, const char * fmt, ...)
836 {
837         va_list args;
838         int i;
839
840         va_start(args,fmt);
841         i = vsscanf(buf,fmt,args);
842         va_end(args);
843         return i;
844 }
845
846 EXPORT_SYMBOL(sscanf);