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