iwlwifi: initialize geo/channel information during probe
[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 /* Decimal conversion is by far the most typical, and is used
139  * for /proc and /sys data. This directly impacts e.g. top performance
140  * with many processes running. We optimize it for speed
141  * using code from
142  * http://www.cs.uiowa.edu/~jones/bcd/decimal.html
143  * (with permission from the author, Douglas W. Jones). */
144
145 /* Formats correctly any integer in [0,99999].
146  * Outputs from one to five digits depending on input.
147  * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */
148 static char* put_dec_trunc(char *buf, unsigned q)
149 {
150         unsigned d3, d2, d1, d0;
151         d1 = (q>>4) & 0xf;
152         d2 = (q>>8) & 0xf;
153         d3 = (q>>12);
154
155         d0 = 6*(d3 + d2 + d1) + (q & 0xf);
156         q = (d0 * 0xcd) >> 11;
157         d0 = d0 - 10*q;
158         *buf++ = d0 + '0'; /* least significant digit */
159         d1 = q + 9*d3 + 5*d2 + d1;
160         if (d1 != 0) {
161                 q = (d1 * 0xcd) >> 11;
162                 d1 = d1 - 10*q;
163                 *buf++ = d1 + '0'; /* next digit */
164
165                 d2 = q + 2*d2;
166                 if ((d2 != 0) || (d3 != 0)) {
167                         q = (d2 * 0xd) >> 7;
168                         d2 = d2 - 10*q;
169                         *buf++ = d2 + '0'; /* next digit */
170
171                         d3 = q + 4*d3;
172                         if (d3 != 0) {
173                                 q = (d3 * 0xcd) >> 11;
174                                 d3 = d3 - 10*q;
175                                 *buf++ = d3 + '0';  /* next digit */
176                                 if (q != 0)
177                                         *buf++ = q + '0';  /* most sign. digit */
178                         }
179                 }
180         }
181         return buf;
182 }
183 /* Same with if's removed. Always emits five digits */
184 static char* put_dec_full(char *buf, unsigned q)
185 {
186         /* BTW, if q is in [0,9999], 8-bit ints will be enough, */
187         /* but anyway, gcc produces better code with full-sized ints */
188         unsigned d3, d2, d1, d0;
189         d1 = (q>>4) & 0xf;
190         d2 = (q>>8) & 0xf;
191         d3 = (q>>12);
192
193         /* Possible ways to approx. divide by 10 */
194         /* gcc -O2 replaces multiply with shifts and adds */
195         // (x * 0xcd) >> 11: 11001101 - shorter code than * 0x67 (on i386)
196         // (x * 0x67) >> 10:  1100111
197         // (x * 0x34) >> 9:    110100 - same
198         // (x * 0x1a) >> 8:     11010 - same
199         // (x * 0x0d) >> 7:      1101 - same, shortest code (on i386)
200
201         d0 = 6*(d3 + d2 + d1) + (q & 0xf);
202         q = (d0 * 0xcd) >> 11;
203         d0 = d0 - 10*q;
204         *buf++ = d0 + '0';
205         d1 = q + 9*d3 + 5*d2 + d1;
206                 q = (d1 * 0xcd) >> 11;
207                 d1 = d1 - 10*q;
208                 *buf++ = d1 + '0';
209
210                 d2 = q + 2*d2;
211                         q = (d2 * 0xd) >> 7;
212                         d2 = d2 - 10*q;
213                         *buf++ = d2 + '0';
214
215                         d3 = q + 4*d3;
216                                 q = (d3 * 0xcd) >> 11; /* - shorter code */
217                                 /* q = (d3 * 0x67) >> 10; - would also work */
218                                 d3 = d3 - 10*q;
219                                 *buf++ = d3 + '0';
220                                         *buf++ = q + '0';
221         return buf;
222 }
223 /* No inlining helps gcc to use registers better */
224 static noinline char* put_dec(char *buf, unsigned long long num)
225 {
226         while (1) {
227                 unsigned rem;
228                 if (num < 100000)
229                         return put_dec_trunc(buf, num);
230                 rem = do_div(num, 100000);
231                 buf = put_dec_full(buf, rem);
232         }
233 }
234
235 #define ZEROPAD 1               /* pad with zero */
236 #define SIGN    2               /* unsigned/signed long */
237 #define PLUS    4               /* show plus */
238 #define SPACE   8               /* space if plus */
239 #define LEFT    16              /* left justified */
240 #define SPECIAL 32              /* 0x */
241 #define LARGE   64              /* use 'ABCDEF' instead of 'abcdef' */
242
243 static char *number(char *buf, char *end, unsigned long long num, int base, int size, int precision, int type)
244 {
245         char sign,tmp[66];
246         const char *digits;
247         /* we are called with base 8, 10 or 16, only, thus don't need "g..."  */
248         static const char small_digits[] = "0123456789abcdefx"; /* "ghijklmnopqrstuvwxyz"; */
249         static const char large_digits[] = "0123456789ABCDEFX"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
250         int need_pfx = ((type & SPECIAL) && base != 10);
251         int i;
252
253         digits = (type & LARGE) ? large_digits : small_digits;
254         if (type & LEFT)
255                 type &= ~ZEROPAD;
256         if (base < 2 || base > 36)
257                 return NULL;
258         sign = 0;
259         if (type & SIGN) {
260                 if ((signed long long) num < 0) {
261                         sign = '-';
262                         num = - (signed long long) num;
263                         size--;
264                 } else if (type & PLUS) {
265                         sign = '+';
266                         size--;
267                 } else if (type & SPACE) {
268                         sign = ' ';
269                         size--;
270                 }
271         }
272         if (need_pfx) {
273                 size--;
274                 if (base == 16)
275                         size--;
276         }
277
278         /* generate full string in tmp[], in reverse order */
279         i = 0;
280         if (num == 0)
281                 tmp[i++] = '0';
282         /* Generic code, for any base:
283         else do {
284                 tmp[i++] = digits[do_div(num,base)];
285         } while (num != 0);
286         */
287         else if (base != 10) { /* 8 or 16 */
288                 int mask = base - 1;
289                 int shift = 3;
290                 if (base == 16) shift = 4;
291                 do {
292                         tmp[i++] = digits[((unsigned char)num) & mask];
293                         num >>= shift;
294                 } while (num);
295         } else { /* base 10 */
296                 i = put_dec(tmp, num) - tmp;
297         }
298
299         /* printing 100 using %2d gives "100", not "00" */
300         if (i > precision)
301                 precision = i;
302         /* leading space padding */
303         size -= precision;
304         if (!(type & (ZEROPAD+LEFT))) {
305                 while(--size >= 0) {
306                         if (buf < end)
307                                 *buf = ' ';
308                         ++buf;
309                 }
310         }
311         /* sign */
312         if (sign) {
313                 if (buf < end)
314                         *buf = sign;
315                 ++buf;
316         }
317         /* "0x" / "0" prefix */
318         if (need_pfx) {
319                 if (buf < end)
320                         *buf = '0';
321                 ++buf;
322                 if (base == 16) {
323                         if (buf < end)
324                                 *buf = digits[16]; /* for arbitrary base: digits[33]; */
325                         ++buf;
326                 }
327         }
328         /* zero or space padding */
329         if (!(type & LEFT)) {
330                 char c = (type & ZEROPAD) ? '0' : ' ';
331                 while (--size >= 0) {
332                         if (buf < end)
333                                 *buf = c;
334                         ++buf;
335                 }
336         }
337         /* hmm even more zero padding? */
338         while (i <= --precision) {
339                 if (buf < end)
340                         *buf = '0';
341                 ++buf;
342         }
343         /* actual digits of result */
344         while (--i >= 0) {
345                 if (buf < end)
346                         *buf = tmp[i];
347                 ++buf;
348         }
349         /* trailing space padding */
350         while (--size >= 0) {
351                 if (buf < end)
352                         *buf = ' ';
353                 ++buf;
354         }
355         return buf;
356 }
357
358 /**
359  * vsnprintf - Format a string and place it in a buffer
360  * @buf: The buffer to place the result into
361  * @size: The size of the buffer, including the trailing null space
362  * @fmt: The format string to use
363  * @args: Arguments for the format string
364  *
365  * The return value is the number of characters which would
366  * be generated for the given input, excluding the trailing
367  * '\0', as per ISO C99. If you want to have the exact
368  * number of characters written into @buf as return value
369  * (not including the trailing '\0'), use vscnprintf(). If the
370  * return is greater than or equal to @size, the resulting
371  * string is truncated.
372  *
373  * Call this function if you are already dealing with a va_list.
374  * You probably want snprintf() instead.
375  */
376 int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
377 {
378         int len;
379         unsigned long long num;
380         int i, base;
381         char *str, *end, c;
382         const char *s;
383
384         int flags;              /* flags to number() */
385
386         int field_width;        /* width of output field */
387         int precision;          /* min. # of digits for integers; max
388                                    number of chars for from string */
389         int qualifier;          /* 'h', 'l', or 'L' for integer fields */
390                                 /* 'z' support added 23/7/1999 S.H.    */
391                                 /* 'z' changed to 'Z' --davidm 1/25/99 */
392                                 /* 't' added for ptrdiff_t */
393
394         /* Reject out-of-range values early.  Large positive sizes are
395            used for unknown buffer sizes. */
396         if (unlikely((int) size < 0)) {
397                 /* There can be only one.. */
398                 static char warn = 1;
399                 WARN_ON(warn);
400                 warn = 0;
401                 return 0;
402         }
403
404         str = buf;
405         end = buf + size;
406
407         /* Make sure end is always >= buf */
408         if (end < buf) {
409                 end = ((void *)-1);
410                 size = end - buf;
411         }
412
413         for (; *fmt ; ++fmt) {
414                 if (*fmt != '%') {
415                         if (str < end)
416                                 *str = *fmt;
417                         ++str;
418                         continue;
419                 }
420
421                 /* process flags */
422                 flags = 0;
423                 repeat:
424                         ++fmt;          /* this also skips first '%' */
425                         switch (*fmt) {
426                                 case '-': flags |= LEFT; goto repeat;
427                                 case '+': flags |= PLUS; goto repeat;
428                                 case ' ': flags |= SPACE; goto repeat;
429                                 case '#': flags |= SPECIAL; goto repeat;
430                                 case '0': flags |= ZEROPAD; goto repeat;
431                         }
432
433                 /* get field width */
434                 field_width = -1;
435                 if (isdigit(*fmt))
436                         field_width = skip_atoi(&fmt);
437                 else if (*fmt == '*') {
438                         ++fmt;
439                         /* it's the next argument */
440                         field_width = va_arg(args, int);
441                         if (field_width < 0) {
442                                 field_width = -field_width;
443                                 flags |= LEFT;
444                         }
445                 }
446
447                 /* get the precision */
448                 precision = -1;
449                 if (*fmt == '.') {
450                         ++fmt;  
451                         if (isdigit(*fmt))
452                                 precision = skip_atoi(&fmt);
453                         else if (*fmt == '*') {
454                                 ++fmt;
455                                 /* it's the next argument */
456                                 precision = va_arg(args, int);
457                         }
458                         if (precision < 0)
459                                 precision = 0;
460                 }
461
462                 /* get the conversion qualifier */
463                 qualifier = -1;
464                 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
465                     *fmt =='Z' || *fmt == 'z' || *fmt == 't') {
466                         qualifier = *fmt;
467                         ++fmt;
468                         if (qualifier == 'l' && *fmt == 'l') {
469                                 qualifier = 'L';
470                                 ++fmt;
471                         }
472                 }
473
474                 /* default base */
475                 base = 10;
476
477                 switch (*fmt) {
478                         case 'c':
479                                 if (!(flags & LEFT)) {
480                                         while (--field_width > 0) {
481                                                 if (str < end)
482                                                         *str = ' ';
483                                                 ++str;
484                                         }
485                                 }
486                                 c = (unsigned char) va_arg(args, int);
487                                 if (str < end)
488                                         *str = c;
489                                 ++str;
490                                 while (--field_width > 0) {
491                                         if (str < end)
492                                                 *str = ' ';
493                                         ++str;
494                                 }
495                                 continue;
496
497                         case 's':
498                                 s = va_arg(args, char *);
499                                 if ((unsigned long)s < PAGE_SIZE)
500                                         s = "<NULL>";
501
502                                 len = strnlen(s, precision);
503
504                                 if (!(flags & LEFT)) {
505                                         while (len < field_width--) {
506                                                 if (str < end)
507                                                         *str = ' ';
508                                                 ++str;
509                                         }
510                                 }
511                                 for (i = 0; i < len; ++i) {
512                                         if (str < end)
513                                                 *str = *s;
514                                         ++str; ++s;
515                                 }
516                                 while (len < field_width--) {
517                                         if (str < end)
518                                                 *str = ' ';
519                                         ++str;
520                                 }
521                                 continue;
522
523                         case 'p':
524                                 if (field_width == -1) {
525                                         field_width = 2*sizeof(void *);
526                                         flags |= ZEROPAD;
527                                 }
528                                 str = number(str, end,
529                                                 (unsigned long) va_arg(args, void *),
530                                                 16, field_width, precision, flags);
531                                 continue;
532
533
534                         case 'n':
535                                 /* FIXME:
536                                 * What does C99 say about the overflow case here? */
537                                 if (qualifier == 'l') {
538                                         long * ip = va_arg(args, long *);
539                                         *ip = (str - buf);
540                                 } else if (qualifier == 'Z' || qualifier == 'z') {
541                                         size_t * ip = va_arg(args, size_t *);
542                                         *ip = (str - buf);
543                                 } else {
544                                         int * ip = va_arg(args, int *);
545                                         *ip = (str - buf);
546                                 }
547                                 continue;
548
549                         case '%':
550                                 if (str < end)
551                                         *str = '%';
552                                 ++str;
553                                 continue;
554
555                                 /* integer number formats - set up the flags and "break" */
556                         case 'o':
557                                 base = 8;
558                                 break;
559
560                         case 'X':
561                                 flags |= LARGE;
562                         case 'x':
563                                 base = 16;
564                                 break;
565
566                         case 'd':
567                         case 'i':
568                                 flags |= SIGN;
569                         case 'u':
570                                 break;
571
572                         default:
573                                 if (str < end)
574                                         *str = '%';
575                                 ++str;
576                                 if (*fmt) {
577                                         if (str < end)
578                                                 *str = *fmt;
579                                         ++str;
580                                 } else {
581                                         --fmt;
582                                 }
583                                 continue;
584                 }
585                 if (qualifier == 'L')
586                         num = va_arg(args, long long);
587                 else if (qualifier == 'l') {
588                         num = va_arg(args, unsigned long);
589                         if (flags & SIGN)
590                                 num = (signed long) num;
591                 } else if (qualifier == 'Z' || qualifier == 'z') {
592                         num = va_arg(args, size_t);
593                 } else if (qualifier == 't') {
594                         num = va_arg(args, ptrdiff_t);
595                 } else if (qualifier == 'h') {
596                         num = (unsigned short) va_arg(args, int);
597                         if (flags & SIGN)
598                                 num = (signed short) num;
599                 } else {
600                         num = va_arg(args, unsigned int);
601                         if (flags & SIGN)
602                                 num = (signed int) num;
603                 }
604                 str = number(str, end, num, base,
605                                 field_width, precision, flags);
606         }
607         if (size > 0) {
608                 if (str < end)
609                         *str = '\0';
610                 else
611                         end[-1] = '\0';
612         }
613         /* the trailing null byte doesn't count towards the total */
614         return str-buf;
615 }
616
617 EXPORT_SYMBOL(vsnprintf);
618
619 /**
620  * vscnprintf - Format a string and place it in a buffer
621  * @buf: The buffer to place the result into
622  * @size: The size of the buffer, including the trailing null space
623  * @fmt: The format string to use
624  * @args: Arguments for the format string
625  *
626  * The return value is the number of characters which have been written into
627  * the @buf not including the trailing '\0'. If @size is <= 0 the function
628  * returns 0.
629  *
630  * Call this function if you are already dealing with a va_list.
631  * You probably want scnprintf() instead.
632  */
633 int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
634 {
635         int i;
636
637         i=vsnprintf(buf,size,fmt,args);
638         return (i >= size) ? (size - 1) : i;
639 }
640
641 EXPORT_SYMBOL(vscnprintf);
642
643 /**
644  * snprintf - Format a string and place it in a buffer
645  * @buf: The buffer to place the result into
646  * @size: The size of the buffer, including the trailing null space
647  * @fmt: The format string to use
648  * @...: Arguments for the format string
649  *
650  * The return value is the number of characters which would be
651  * generated for the given input, excluding the trailing null,
652  * as per ISO C99.  If the return is greater than or equal to
653  * @size, the resulting string is truncated.
654  */
655 int snprintf(char * buf, size_t size, const char *fmt, ...)
656 {
657         va_list args;
658         int i;
659
660         va_start(args, fmt);
661         i=vsnprintf(buf,size,fmt,args);
662         va_end(args);
663         return i;
664 }
665
666 EXPORT_SYMBOL(snprintf);
667
668 /**
669  * scnprintf - Format a string and place it in a buffer
670  * @buf: The buffer to place the result into
671  * @size: The size of the buffer, including the trailing null space
672  * @fmt: The format string to use
673  * @...: Arguments for the format string
674  *
675  * The return value is the number of characters written into @buf not including
676  * the trailing '\0'. If @size is <= 0 the function returns 0.
677  */
678
679 int scnprintf(char * buf, size_t size, const char *fmt, ...)
680 {
681         va_list args;
682         int i;
683
684         va_start(args, fmt);
685         i = vsnprintf(buf, size, fmt, args);
686         va_end(args);
687         return (i >= size) ? (size - 1) : i;
688 }
689 EXPORT_SYMBOL(scnprintf);
690
691 /**
692  * vsprintf - Format a string and place it in a buffer
693  * @buf: The buffer to place the result into
694  * @fmt: The format string to use
695  * @args: Arguments for the format string
696  *
697  * The function returns the number of characters written
698  * into @buf. Use vsnprintf() or vscnprintf() in order to avoid
699  * buffer overflows.
700  *
701  * Call this function if you are already dealing with a va_list.
702  * You probably want sprintf() instead.
703  */
704 int vsprintf(char *buf, const char *fmt, va_list args)
705 {
706         return vsnprintf(buf, INT_MAX, fmt, args);
707 }
708
709 EXPORT_SYMBOL(vsprintf);
710
711 /**
712  * sprintf - Format a string and place it in a buffer
713  * @buf: The buffer to place the result into
714  * @fmt: The format string to use
715  * @...: Arguments for the format string
716  *
717  * The function returns the number of characters written
718  * into @buf. Use snprintf() or scnprintf() in order to avoid
719  * buffer overflows.
720  */
721 int sprintf(char * buf, const char *fmt, ...)
722 {
723         va_list args;
724         int i;
725
726         va_start(args, fmt);
727         i=vsnprintf(buf, INT_MAX, fmt, args);
728         va_end(args);
729         return i;
730 }
731
732 EXPORT_SYMBOL(sprintf);
733
734 /**
735  * vsscanf - Unformat a buffer into a list of arguments
736  * @buf:        input buffer
737  * @fmt:        format of buffer
738  * @args:       arguments
739  */
740 int vsscanf(const char * buf, const char * fmt, va_list args)
741 {
742         const char *str = buf;
743         char *next;
744         char digit;
745         int num = 0;
746         int qualifier;
747         int base;
748         int field_width;
749         int is_sign = 0;
750
751         while(*fmt && *str) {
752                 /* skip any white space in format */
753                 /* white space in format matchs any amount of
754                  * white space, including none, in the input.
755                  */
756                 if (isspace(*fmt)) {
757                         while (isspace(*fmt))
758                                 ++fmt;
759                         while (isspace(*str))
760                                 ++str;
761                 }
762
763                 /* anything that is not a conversion must match exactly */
764                 if (*fmt != '%' && *fmt) {
765                         if (*fmt++ != *str++)
766                                 break;
767                         continue;
768                 }
769
770                 if (!*fmt)
771                         break;
772                 ++fmt;
773                 
774                 /* skip this conversion.
775                  * advance both strings to next white space
776                  */
777                 if (*fmt == '*') {
778                         while (!isspace(*fmt) && *fmt)
779                                 fmt++;
780                         while (!isspace(*str) && *str)
781                                 str++;
782                         continue;
783                 }
784
785                 /* get field width */
786                 field_width = -1;
787                 if (isdigit(*fmt))
788                         field_width = skip_atoi(&fmt);
789
790                 /* get conversion qualifier */
791                 qualifier = -1;
792                 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
793                     *fmt == 'Z' || *fmt == 'z') {
794                         qualifier = *fmt++;
795                         if (unlikely(qualifier == *fmt)) {
796                                 if (qualifier == 'h') {
797                                         qualifier = 'H';
798                                         fmt++;
799                                 } else if (qualifier == 'l') {
800                                         qualifier = 'L';
801                                         fmt++;
802                                 }
803                         }
804                 }
805                 base = 10;
806                 is_sign = 0;
807
808                 if (!*fmt || !*str)
809                         break;
810
811                 switch(*fmt++) {
812                 case 'c':
813                 {
814                         char *s = (char *) va_arg(args,char*);
815                         if (field_width == -1)
816                                 field_width = 1;
817                         do {
818                                 *s++ = *str++;
819                         } while (--field_width > 0 && *str);
820                         num++;
821                 }
822                 continue;
823                 case 's':
824                 {
825                         char *s = (char *) va_arg(args, char *);
826                         if(field_width == -1)
827                                 field_width = INT_MAX;
828                         /* first, skip leading white space in buffer */
829                         while (isspace(*str))
830                                 str++;
831
832                         /* now copy until next white space */
833                         while (*str && !isspace(*str) && field_width--) {
834                                 *s++ = *str++;
835                         }
836                         *s = '\0';
837                         num++;
838                 }
839                 continue;
840                 case 'n':
841                         /* return number of characters read so far */
842                 {
843                         int *i = (int *)va_arg(args,int*);
844                         *i = str - buf;
845                 }
846                 continue;
847                 case 'o':
848                         base = 8;
849                         break;
850                 case 'x':
851                 case 'X':
852                         base = 16;
853                         break;
854                 case 'i':
855                         base = 0;
856                 case 'd':
857                         is_sign = 1;
858                 case 'u':
859                         break;
860                 case '%':
861                         /* looking for '%' in str */
862                         if (*str++ != '%') 
863                                 return num;
864                         continue;
865                 default:
866                         /* invalid format; stop here */
867                         return num;
868                 }
869
870                 /* have some sort of integer conversion.
871                  * first, skip white space in buffer.
872                  */
873                 while (isspace(*str))
874                         str++;
875
876                 digit = *str;
877                 if (is_sign && digit == '-')
878                         digit = *(str + 1);
879
880                 if (!digit
881                     || (base == 16 && !isxdigit(digit))
882                     || (base == 10 && !isdigit(digit))
883                     || (base == 8 && (!isdigit(digit) || digit > '7'))
884                     || (base == 0 && !isdigit(digit)))
885                                 break;
886
887                 switch(qualifier) {
888                 case 'H':       /* that's 'hh' in format */
889                         if (is_sign) {
890                                 signed char *s = (signed char *) va_arg(args,signed char *);
891                                 *s = (signed char) simple_strtol(str,&next,base);
892                         } else {
893                                 unsigned char *s = (unsigned char *) va_arg(args, unsigned char *);
894                                 *s = (unsigned char) simple_strtoul(str, &next, base);
895                         }
896                         break;
897                 case 'h':
898                         if (is_sign) {
899                                 short *s = (short *) va_arg(args,short *);
900                                 *s = (short) simple_strtol(str,&next,base);
901                         } else {
902                                 unsigned short *s = (unsigned short *) va_arg(args, unsigned short *);
903                                 *s = (unsigned short) simple_strtoul(str, &next, base);
904                         }
905                         break;
906                 case 'l':
907                         if (is_sign) {
908                                 long *l = (long *) va_arg(args,long *);
909                                 *l = simple_strtol(str,&next,base);
910                         } else {
911                                 unsigned long *l = (unsigned long*) va_arg(args,unsigned long*);
912                                 *l = simple_strtoul(str,&next,base);
913                         }
914                         break;
915                 case 'L':
916                         if (is_sign) {
917                                 long long *l = (long long*) va_arg(args,long long *);
918                                 *l = simple_strtoll(str,&next,base);
919                         } else {
920                                 unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*);
921                                 *l = simple_strtoull(str,&next,base);
922                         }
923                         break;
924                 case 'Z':
925                 case 'z':
926                 {
927                         size_t *s = (size_t*) va_arg(args,size_t*);
928                         *s = (size_t) simple_strtoul(str,&next,base);
929                 }
930                 break;
931                 default:
932                         if (is_sign) {
933                                 int *i = (int *) va_arg(args, int*);
934                                 *i = (int) simple_strtol(str,&next,base);
935                         } else {
936                                 unsigned int *i = (unsigned int*) va_arg(args, unsigned int*);
937                                 *i = (unsigned int) simple_strtoul(str,&next,base);
938                         }
939                         break;
940                 }
941                 num++;
942
943                 if (!next)
944                         break;
945                 str = next;
946         }
947
948         /*
949          * Now we've come all the way through so either the input string or the
950          * format ended. In the former case, there can be a %n at the current
951          * position in the format that needs to be filled.
952          */
953         if (*fmt == '%' && *(fmt + 1) == 'n') {
954                 int *p = (int *)va_arg(args, int *);
955                 *p = str - buf;
956         }
957
958         return num;
959 }
960
961 EXPORT_SYMBOL(vsscanf);
962
963 /**
964  * sscanf - Unformat a buffer into a list of arguments
965  * @buf:        input buffer
966  * @fmt:        formatting of buffer
967  * @...:        resulting arguments
968  */
969 int sscanf(const char * buf, const char * fmt, ...)
970 {
971         va_list args;
972         int i;
973
974         va_start(args,fmt);
975         i = vsscanf(buf,fmt,args);
976         va_end(args);
977         return i;
978 }
979
980 EXPORT_SYMBOL(sscanf);