Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Merge branch 'devel'
[palacios.git] / kitten / 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 <lwk/linux_compat.h>
21 #include <lwk/types.h>
22 #include <lwk/string.h>
23 #include <lwk/ctype.h>
24 #include <lwk/kernel.h>
25
26 #include <arch/page.h>          /* for PAGE_SIZE */
27 #include <arch/div64.h>
28
29 /**
30  * simple_strtoul - convert a string to an unsigned long
31  * @cp: The start of the string
32  * @endp: A pointer to the end of the parsed string will be placed here
33  * @base: The number base to use
34  */
35 unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
36 {
37         unsigned long result = 0,value;
38
39         if (!base) {
40                 base = 10;
41                 if (*cp == '0') {
42                         base = 8;
43                         cp++;
44                         if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
45                                 cp++;
46                                 base = 16;
47                         }
48                 }
49         } else if (base == 16) {
50                 if (cp[0] == '0' && toupper(cp[1]) == 'X')
51                         cp += 2;
52         }
53         while (isxdigit(*cp) &&
54                (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
55                 result = result*base + value;
56                 cp++;
57         }
58         if (endp)
59                 *endp = (char *)cp;
60         return result;
61 }
62
63 EXPORT_SYMBOL(simple_strtoul);
64
65 /**
66  * simple_strtol - convert a string to a signed long
67  * @cp: The start of the string
68  * @endp: A pointer to the end of the parsed string will be placed here
69  * @base: The number base to use
70  */
71 long simple_strtol(const char *cp,char **endp,unsigned int base)
72 {
73         if(*cp=='-')
74                 return -simple_strtoul(cp+1,endp,base);
75         return simple_strtoul(cp,endp,base);
76 }
77
78 EXPORT_SYMBOL(simple_strtol);
79
80 /**
81  * simple_strtoull - convert a string to an unsigned long long
82  * @cp: The start of the string
83  * @endp: A pointer to the end of the parsed string will be placed here
84  * @base: The number base to use
85  */
86 unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
87 {
88         unsigned long long result = 0,value;
89
90         if (!base) {
91                 base = 10;
92                 if (*cp == '0') {
93                         base = 8;
94                         cp++;
95                         if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
96                                 cp++;
97                                 base = 16;
98                         }
99                 }
100         } else if (base == 16) {
101                 if (cp[0] == '0' && toupper(cp[1]) == 'X')
102                         cp += 2;
103         }
104         while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
105             ? toupper(*cp) : *cp)-'A'+10) < base) {
106                 result = result*base + value;
107                 cp++;
108         }
109         if (endp)
110                 *endp = (char *)cp;
111         return result;
112 }
113
114 EXPORT_SYMBOL(simple_strtoull);
115
116 /**
117  * simple_strtoll - convert a string to a signed long long
118  * @cp: The start of the string
119  * @endp: A pointer to the end of the parsed string will be placed here
120  * @base: The number base to use
121  */
122 long long simple_strtoll(const char *cp,char **endp,unsigned int base)
123 {
124         if(*cp=='-')
125                 return -simple_strtoull(cp+1,endp,base);
126         return simple_strtoull(cp,endp,base);
127 }
128
129 static int skip_atoi(const char **s)
130 {
131         int i=0;
132
133         while (isdigit(**s))
134                 i = i*10 + *((*s)++) - '0';
135         return i;
136 }
137
138 #define ZEROPAD 1               /* pad with zero */
139 #define SIGN    2               /* unsigned/signed long */
140 #define PLUS    4               /* show plus */
141 #define SPACE   8               /* space if plus */
142 #define LEFT    16              /* left justified */
143 #define SPECIAL 32              /* 0x */
144 #define LARGE   64              /* use 'ABCDEF' instead of 'abcdef' */
145
146 static char * number(char * buf, char * end, unsigned long long num, int base, int size, int precision, int type)
147 {
148         char c,sign,tmp[66];
149         const char *digits;
150         static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
151         static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
152         int i;
153
154         digits = (type & LARGE) ? large_digits : small_digits;
155         if (type & LEFT)
156                 type &= ~ZEROPAD;
157         if (base < 2 || base > 36)
158                 return NULL;
159         c = (type & ZEROPAD) ? '0' : ' ';
160         sign = 0;
161         if (type & SIGN) {
162                 if ((signed long long) num < 0) {
163                         sign = '-';
164                         num = - (signed long long) num;
165                         size--;
166                 } else if (type & PLUS) {
167                         sign = '+';
168                         size--;
169                 } else if (type & SPACE) {
170                         sign = ' ';
171                         size--;
172                 }
173         }
174         if (type & SPECIAL) {
175                 if (base == 16)
176                         size -= 2;
177                 else if (base == 8)
178                         size--;
179         }
180         i = 0;
181         if (num == 0)
182                 tmp[i++]='0';
183         else while (num != 0)
184                 tmp[i++] = digits[do_div(num,base)];
185         if (i > precision)
186                 precision = i;
187         size -= precision;
188         if (!(type&(ZEROPAD+LEFT))) {
189                 while(size-->0) {
190                         if (buf <= end)
191                                 *buf = ' ';
192                         ++buf;
193                 }
194         }
195         if (sign) {
196                 if (buf <= end)
197                         *buf = sign;
198                 ++buf;
199         }
200         if (type & SPECIAL) {
201                 if (base==8) {
202                         if (buf <= end)
203                                 *buf = '0';
204                         ++buf;
205                 } else if (base==16) {
206                         if (buf <= end)
207                                 *buf = '0';
208                         ++buf;
209                         if (buf <= end)
210                                 *buf = digits[33];
211                         ++buf;
212                 }
213         }
214         if (!(type & LEFT)) {
215                 while (size-- > 0) {
216                         if (buf <= end)
217                                 *buf = c;
218                         ++buf;
219                 }
220         }
221         while (i < precision--) {
222                 if (buf <= end)
223                         *buf = '0';
224                 ++buf;
225         }
226         while (i-- > 0) {
227                 if (buf <= end)
228                         *buf = tmp[i];
229                 ++buf;
230         }
231         while (size-- > 0) {
232                 if (buf <= end)
233                         *buf = ' ';
234                 ++buf;
235         }
236         return buf;
237 }
238
239 /**
240  * vsnprintf - Format a string and place it in a buffer
241  * @buf: The buffer to place the result into
242  * @size: The size of the buffer, including the trailing null space
243  * @fmt: The format string to use
244  * @args: Arguments for the format string
245  *
246  * The return value is the number of characters which would
247  * be generated for the given input, excluding the trailing
248  * '\0', as per ISO C99. If you want to have the exact
249  * number of characters written into @buf as return value
250  * (not including the trailing '\0'), use vscnprintf. If the
251  * return is greater than or equal to @size, the resulting
252  * string is truncated.
253  *
254  * Call this function if you are already dealing with a va_list.
255  * You probably want snprintf instead.
256  */
257 int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
258 {
259         int len;
260         unsigned long long num;
261         int i, base;
262         char *str, *end, c;
263         const char *s;
264
265         int flags;              /* flags to number() */
266
267         int field_width;        /* width of output field */
268         int precision;          /* min. # of digits for integers; max
269                                    number of chars for from string */
270         int qualifier;          /* 'h', 'l', or 'L' for integer fields */
271                                 /* 'z' support added 23/7/1999 S.H.    */
272                                 /* 'z' changed to 'Z' --davidm 1/25/99 */
273                                 /* 't' added for ptrdiff_t */
274
275         /* Reject out-of-range values early */
276         if (unlikely((int) size < 0)) {
277                 /* There can be only one.. */
278                 static int warn = 1;
279                 WARN_ON(warn);
280                 warn = 0;
281                 return 0;
282         }
283
284         str = buf;
285         end = buf + size - 1;
286
287         if (end < buf - 1) {
288                 end = ((void *) -1);
289                 size = end - buf + 1;
290         }
291
292         for (; *fmt ; ++fmt) {
293                 if (*fmt != '%') {
294                         if (str <= end)
295                                 *str = *fmt;
296                         ++str;
297                         continue;
298                 }
299
300                 /* process flags */
301                 flags = 0;
302                 repeat:
303                         ++fmt;          /* this also skips first '%' */
304                         switch (*fmt) {
305                                 case '-': flags |= LEFT; goto repeat;
306                                 case '+': flags |= PLUS; goto repeat;
307                                 case ' ': flags |= SPACE; goto repeat;
308                                 case '#': flags |= SPECIAL; goto repeat;
309                                 case '0': flags |= ZEROPAD; goto repeat;
310                         }
311
312                 /* get field width */
313                 field_width = -1;
314                 if (isdigit(*fmt))
315                         field_width = skip_atoi(&fmt);
316                 else if (*fmt == '*') {
317                         ++fmt;
318                         /* it's the next argument */
319                         field_width = va_arg(args, int);
320                         if (field_width < 0) {
321                                 field_width = -field_width;
322                                 flags |= LEFT;
323                         }
324                 }
325
326                 /* get the precision */
327                 precision = -1;
328                 if (*fmt == '.') {
329                         ++fmt;  
330                         if (isdigit(*fmt))
331                                 precision = skip_atoi(&fmt);
332                         else if (*fmt == '*') {
333                                 ++fmt;
334                                 /* it's the next argument */
335                                 precision = va_arg(args, int);
336                         }
337                         if (precision < 0)
338                                 precision = 0;
339                 }
340
341                 /* get the conversion qualifier */
342                 qualifier = -1;
343                 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
344                     *fmt =='Z' || *fmt == 'z' || *fmt == 't') {
345                         qualifier = *fmt;
346                         ++fmt;
347                         if (qualifier == 'l' && *fmt == 'l') {
348                                 qualifier = 'L';
349                                 ++fmt;
350                         }
351                 }
352
353                 /* default base */
354                 base = 10;
355
356                 switch (*fmt) {
357                         case 'c':
358                                 if (!(flags & LEFT)) {
359                                         while (--field_width > 0) {
360                                                 if (str <= end)
361                                                         *str = ' ';
362                                                 ++str;
363                                         }
364                                 }
365                                 c = (unsigned char) va_arg(args, int);
366                                 if (str <= end)
367                                         *str = c;
368                                 ++str;
369                                 while (--field_width > 0) {
370                                         if (str <= end)
371                                                 *str = ' ';
372                                         ++str;
373                                 }
374                                 continue;
375
376                         case 's':
377                                 s = va_arg(args, char *);
378                                 if ((unsigned long)s < PAGE_SIZE)
379                                         s = "<NULL>";
380
381                                 len = strnlen(s, precision);
382
383                                 if (!(flags & LEFT)) {
384                                         while (len < field_width--) {
385                                                 if (str <= end)
386                                                         *str = ' ';
387                                                 ++str;
388                                         }
389                                 }
390                                 for (i = 0; i < len; ++i) {
391                                         if (str <= end)
392                                                 *str = *s;
393                                         ++str; ++s;
394                                 }
395                                 while (len < field_width--) {
396                                         if (str <= end)
397                                                 *str = ' ';
398                                         ++str;
399                                 }
400                                 continue;
401
402                         case 'p':
403                                 if (field_width == -1) {
404                                         field_width = 2*sizeof(void *);
405                                         flags |= ZEROPAD;
406                                 }
407                                 str = number(str, end,
408                                                 (unsigned long) va_arg(args, void *),
409                                                 16, field_width, precision, flags);
410                                 continue;
411
412
413                         case 'n':
414                                 /* FIXME:
415                                 * What does C99 say about the overflow case here? */
416                                 if (qualifier == 'l') {
417                                         long * ip = va_arg(args, long *);
418                                         *ip = (str - buf);
419                                 } else if (qualifier == 'Z' || qualifier == 'z') {
420                                         size_t * ip = va_arg(args, size_t *);
421                                         *ip = (str - buf);
422                                 } else {
423                                         int * ip = va_arg(args, int *);
424                                         *ip = (str - buf);
425                                 }
426                                 continue;
427
428                         case '%':
429                                 if (str <= end)
430                                         *str = '%';
431                                 ++str;
432                                 continue;
433
434                                 /* integer number formats - set up the flags and "break" */
435                         case 'o':
436                                 base = 8;
437                                 break;
438
439                         case 'X':
440                                 flags |= LARGE;
441                         case 'x':
442                                 base = 16;
443                                 break;
444
445                         case 'd':
446                         case 'i':
447                                 flags |= SIGN;
448                         case 'u':
449                                 break;
450
451                         default:
452                                 if (str <= end)
453                                         *str = '%';
454                                 ++str;
455                                 if (*fmt) {
456                                         if (str <= end)
457                                                 *str = *fmt;
458                                         ++str;
459                                 } else {
460                                         --fmt;
461                                 }
462                                 continue;
463                 }
464                 if (qualifier == 'L')
465                         num = va_arg(args, long long);
466                 else if (qualifier == 'l') {
467                         num = va_arg(args, unsigned long);
468                         if (flags & SIGN)
469                                 num = (signed long) num;
470                 } else if (qualifier == 'Z' || qualifier == 'z') {
471                         num = va_arg(args, size_t);
472                 } else if (qualifier == 't') {
473                         num = va_arg(args, ptrdiff_t);
474                 } else if (qualifier == 'h') {
475                         num = (unsigned short) va_arg(args, int);
476                         if (flags & SIGN)
477                                 num = (signed short) num;
478                 } else {
479                         num = va_arg(args, unsigned int);
480                         if (flags & SIGN)
481                                 num = (signed int) num;
482                 }
483                 str = number(str, end, num, base,
484                                 field_width, precision, flags);
485         }
486         if (str <= end)
487                 *str = '\0';
488         else if (size > 0)
489                 /* don't write out a null byte if the buf size is zero */
490                 *end = '\0';
491         /* the trailing null byte doesn't count towards the total
492         * ++str;
493         */
494         return str-buf;
495 }
496
497 EXPORT_SYMBOL(vsnprintf);
498
499 /**
500  * vscnprintf - Format a string and place it in a buffer
501  * @buf: The buffer to place the result into
502  * @size: The size of the buffer, including the trailing null space
503  * @fmt: The format string to use
504  * @args: Arguments for the format string
505  *
506  * The return value is the number of characters which have been written into
507  * the @buf not including the trailing '\0'. If @size is <= 0 the function
508  * returns 0.
509  *
510  * Call this function if you are already dealing with a va_list.
511  * You probably want scnprintf instead.
512  */
513 int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
514 {
515         int i;
516
517         i=vsnprintf(buf,size,fmt,args);
518         return (i >= size) ? (size - 1) : i;
519 }
520
521 EXPORT_SYMBOL(vscnprintf);
522
523 /**
524  * snprintf - Format a string and place it in a buffer
525  * @buf: The buffer to place the result into
526  * @size: The size of the buffer, including the trailing null space
527  * @fmt: The format string to use
528  * @...: Arguments for the format string
529  *
530  * The return value is the number of characters which would be
531  * generated for the given input, excluding the trailing null,
532  * as per ISO C99.  If the return is greater than or equal to
533  * @size, the resulting string is truncated.
534  */
535 int snprintf(char * buf, size_t size, const char *fmt, ...)
536 {
537         va_list args;
538         int i;
539
540         va_start(args, fmt);
541         i=vsnprintf(buf,size,fmt,args);
542         va_end(args);
543         return i;
544 }
545
546 EXPORT_SYMBOL(snprintf);
547
548 /**
549  * scnprintf - Format a string and place it in a buffer
550  * @buf: The buffer to place the result into
551  * @size: The size of the buffer, including the trailing null space
552  * @fmt: The format string to use
553  * @...: Arguments for the format string
554  *
555  * The return value is the number of characters written into @buf not including
556  * the trailing '\0'. If @size is <= 0 the function returns 0. If the return is
557  * greater than or equal to @size, the resulting string is truncated.
558  */
559
560 int scnprintf(char * buf, size_t size, const char *fmt, ...)
561 {
562         va_list args;
563         int i;
564
565         va_start(args, fmt);
566         i = vsnprintf(buf, size, fmt, args);
567         va_end(args);
568         return (i >= size) ? (size - 1) : i;
569 }
570 EXPORT_SYMBOL(scnprintf);
571
572 /**
573  * vsprintf - Format a string and place it in a buffer
574  * @buf: The buffer to place the result into
575  * @fmt: The format string to use
576  * @args: Arguments for the format string
577  *
578  * The function returns the number of characters written
579  * into @buf. Use vsnprintf or vscnprintf in order to avoid
580  * buffer overflows.
581  *
582  * Call this function if you are already dealing with a va_list.
583  * You probably want sprintf instead.
584  */
585 int vsprintf(char *buf, const char *fmt, va_list args)
586 {
587         return vsnprintf(buf, INT_MAX, fmt, args);
588 }
589
590 EXPORT_SYMBOL(vsprintf);
591
592 /**
593  * sprintf - Format a string and place it in a buffer
594  * @buf: The buffer to place the result into
595  * @fmt: The format string to use
596  * @...: Arguments for the format string
597  *
598  * The function returns the number of characters written
599  * into @buf. Use snprintf or scnprintf in order to avoid
600  * buffer overflows.
601  */
602 int sprintf(char * buf, const char *fmt, ...)
603 {
604         va_list args;
605         int i;
606
607         va_start(args, fmt);
608         i=vsnprintf(buf, INT_MAX, fmt, args);
609         va_end(args);
610         return i;
611 }
612
613 EXPORT_SYMBOL(sprintf);
614
615 /**
616  * vsscanf - Unformat a buffer into a list of arguments
617  * @buf:        input buffer
618  * @fmt:        format of buffer
619  * @args:       arguments
620  */
621 int vsscanf(const char * buf, const char * fmt, va_list args)
622 {
623         const char *str = buf;
624         char *next;
625         char digit;
626         int num = 0;
627         int qualifier;
628         int base;
629         int field_width;
630         int is_sign = 0;
631
632         while(*fmt && *str) {
633                 /* skip any white space in format */
634                 /* white space in format matchs any amount of
635                  * white space, including none, in the input.
636                  */
637                 if (isspace(*fmt)) {
638                         while (isspace(*fmt))
639                                 ++fmt;
640                         while (isspace(*str))
641                                 ++str;
642                 }
643
644                 /* anything that is not a conversion must match exactly */
645                 if (*fmt != '%' && *fmt) {
646                         if (*fmt++ != *str++)
647                                 break;
648                         continue;
649                 }
650
651                 if (!*fmt)
652                         break;
653                 ++fmt;
654                 
655                 /* skip this conversion.
656                  * advance both strings to next white space
657                  */
658                 if (*fmt == '*') {
659                         while (!isspace(*fmt) && *fmt)
660                                 fmt++;
661                         while (!isspace(*str) && *str)
662                                 str++;
663                         continue;
664                 }
665
666                 /* get field width */
667                 field_width = -1;
668                 if (isdigit(*fmt))
669                         field_width = skip_atoi(&fmt);
670
671                 /* get conversion qualifier */
672                 qualifier = -1;
673                 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
674                     *fmt == 'Z' || *fmt == 'z') {
675                         qualifier = *fmt++;
676                         if (unlikely(qualifier == *fmt)) {
677                                 if (qualifier == 'h') {
678                                         qualifier = 'H';
679                                         fmt++;
680                                 } else if (qualifier == 'l') {
681                                         qualifier = 'L';
682                                         fmt++;
683                                 }
684                         }
685                 }
686                 base = 10;
687                 is_sign = 0;
688
689                 if (!*fmt || !*str)
690                         break;
691
692                 switch(*fmt++) {
693                 case 'c':
694                 {
695                         char *s = (char *) va_arg(args,char*);
696                         if (field_width == -1)
697                                 field_width = 1;
698                         do {
699                                 *s++ = *str++;
700                         } while (--field_width > 0 && *str);
701                         num++;
702                 }
703                 continue;
704                 case 's':
705                 {
706                         char *s = (char *) va_arg(args, char *);
707                         if(field_width == -1)
708                                 field_width = INT_MAX;
709                         /* first, skip leading white space in buffer */
710                         while (isspace(*str))
711                                 str++;
712
713                         /* now copy until next white space */
714                         while (*str && !isspace(*str) && field_width--) {
715                                 *s++ = *str++;
716                         }
717                         *s = '\0';
718                         num++;
719                 }
720                 continue;
721                 case 'n':
722                         /* return number of characters read so far */
723                 {
724                         int *i = (int *)va_arg(args,int*);
725                         *i = str - buf;
726                 }
727                 continue;
728                 case 'o':
729                         base = 8;
730                         break;
731                 case 'x':
732                 case 'X':
733                         base = 16;
734                         break;
735                 case 'i':
736                         base = 0;
737                 case 'd':
738                         is_sign = 1;
739                 case 'u':
740                         break;
741                 case '%':
742                         /* looking for '%' in str */
743                         if (*str++ != '%') 
744                                 return num;
745                         continue;
746                 default:
747                         /* invalid format; stop here */
748                         return num;
749                 }
750
751                 /* have some sort of integer conversion.
752                  * first, skip white space in buffer.
753                  */
754                 while (isspace(*str))
755                         str++;
756
757                 digit = *str;
758                 if (is_sign && digit == '-')
759                         digit = *(str + 1);
760
761                 if (!digit
762                     || (base == 16 && !isxdigit(digit))
763                     || (base == 10 && !isdigit(digit))
764                     || (base == 8 && (!isdigit(digit) || digit > '7'))
765                     || (base == 0 && !isdigit(digit)))
766                                 break;
767
768                 switch(qualifier) {
769                 case 'H':       /* that's 'hh' in format */
770                         if (is_sign) {
771                                 signed char *s = (signed char *) va_arg(args,signed char *);
772                                 *s = (signed char) simple_strtol(str,&next,base);
773                         } else {
774                                 unsigned char *s = (unsigned char *) va_arg(args, unsigned char *);
775                                 *s = (unsigned char) simple_strtoul(str, &next, base);
776                         }
777                         break;
778                 case 'h':
779                         if (is_sign) {
780                                 short *s = (short *) va_arg(args,short *);
781                                 *s = (short) simple_strtol(str,&next,base);
782                         } else {
783                                 unsigned short *s = (unsigned short *) va_arg(args, unsigned short *);
784                                 *s = (unsigned short) simple_strtoul(str, &next, base);
785                         }
786                         break;
787                 case 'l':
788                         if (is_sign) {
789                                 long *l = (long *) va_arg(args,long *);
790                                 *l = simple_strtol(str,&next,base);
791                         } else {
792                                 unsigned long *l = (unsigned long*) va_arg(args,unsigned long*);
793                                 *l = simple_strtoul(str,&next,base);
794                         }
795                         break;
796                 case 'L':
797                         if (is_sign) {
798                                 long long *l = (long long*) va_arg(args,long long *);
799                                 *l = simple_strtoll(str,&next,base);
800                         } else {
801                                 unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*);
802                                 *l = simple_strtoull(str,&next,base);
803                         }
804                         break;
805                 case 'Z':
806                 case 'z':
807                 {
808                         size_t *s = (size_t*) va_arg(args,size_t*);
809                         *s = (size_t) simple_strtoul(str,&next,base);
810                 }
811                 break;
812                 default:
813                         if (is_sign) {
814                                 int *i = (int *) va_arg(args, int*);
815                                 *i = (int) simple_strtol(str,&next,base);
816                         } else {
817                                 unsigned int *i = (unsigned int*) va_arg(args, unsigned int*);
818                                 *i = (unsigned int) simple_strtoul(str,&next,base);
819                         }
820                         break;
821                 }
822                 num++;
823
824                 if (!next)
825                         break;
826                 str = next;
827         }
828         return num;
829 }
830
831 EXPORT_SYMBOL(vsscanf);
832
833 /**
834  * sscanf - Unformat a buffer into a list of arguments
835  * @buf:        input buffer
836  * @fmt:        formatting of buffer
837  * @...:        resulting arguments
838  */
839 int sscanf(const char * buf, const char * fmt, ...)
840 {
841         va_list args;
842         int i;
843
844         va_start(args,fmt);
845         i = vsscanf(buf,fmt,args);
846         va_end(args);
847         return i;
848 }
849
850 EXPORT_SYMBOL(sscanf);