Subversion Repositories shark

Rev

Rev 455 | Details | Compare with Previous | Last modification | View Log | RSS feed

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