Statistics
| Branch: | Revision:

root / prex-0.9.0 / sys / lib / vsprintf.c @ 03e9c04a

History | View | Annotate | Download (3.32 KB)

1
/*-
2
 * Copyright (c) 2005, Kohsuke Ohtani
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. Neither the name of the author nor the names of any co-contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29

    
30
/*
31
 * vsprintf.c - Format and output data to buffer
32
 */
33

    
34
#include <kernel.h>
35

    
36
#define isdigit(c)  ((u_int)((c) - '0') < 10)
37

    
38
static u_long
39
divide(long *n, int base)
40
{
41
        u_long res;
42

    
43
        res = ((u_long)*n) % base;
44
        *n = (long)(((u_long)*n) / base);
45
        return res;
46
}
47

    
48
static int
49
atoi(const char **s)
50
{
51
        int i = 0;
52
        while (isdigit((int)**s))
53
                i = i * 10 + *((*s)++) - '0';
54
        return i;
55
}
56

    
57
/*
58
 * Print formatted output - scaled down version
59
 *
60
 * Identifiers:
61
 *  %d - Decimal signed int
62
 *  %x - Hex integer
63
 *  %u - Unsigned integer
64
 *  %c - Character
65
 *  %s - String
66
 *
67
 * Flags:
68
 *   0 - Zero pad
69
 */
70
int
71
vsprintf(char *buf, const char *fmt, va_list args)
72
{
73
        char *p, *str;
74
        const char *digits = "0123456789abcdef";
75
        char pad, tmp[16];
76
        int width, base, sign, i;
77
        long num;
78

    
79
        for (p = buf; *fmt; fmt++) {
80
                if (*fmt != '%') {
81
                        *p++ = *fmt;
82
                        continue;
83
                }
84
                /* get flags */
85
                ++fmt;
86
                pad = ' ';
87
                if (*fmt == '0') {
88
                        pad = '0';
89
                        fmt++;
90
                }
91
                /* get width */
92
                width = -1;
93
                if (isdigit(*fmt)) {
94
                        width = atoi(&fmt);
95
                }
96
                /* ignore long */
97
                if (*fmt == 'l')
98
                        fmt++;
99
                base = 10;
100
                sign = 0;
101
                switch (*fmt) {
102
                case 'c':
103
                        *p++ = (char)va_arg(args, int);
104
                        continue;
105
                case 's':
106
                        str = va_arg(args, char *);
107
                        if (str == NULL)
108
                                str = "<NULL>";
109
                        for (; *str && width != 0; str++, width--) {
110
                                *p++ = *str;
111
                        }
112
                        while (width-- > 0)
113
                                *p++ = pad;
114
                        continue;
115
                case 'X':
116
                case 'x':
117
                        base = 16;
118
                        break;
119
                case 'd':
120
                        sign = 1;
121
                        break;
122
                case 'u':
123
                        break;
124
                default:
125
                        continue;
126
                }
127
                num = va_arg(args, long);
128
                if (sign && num < 0) {
129
                        num = -num;
130
                        *p++ = '-';
131
                        width--;
132
                }
133
                i = 0;
134
                if (num == 0)
135
                        tmp[i++] = '0';
136
                else
137
                        while (num != 0)
138
                                tmp[i++] = digits[divide(&num, base)];
139
                width -= i;
140
                while (width-- > 0)
141
                        *p++ = pad;
142
                while (i-- > 0)
143
                        *p++ = tmp[i];
144
        }
145
        *p = '\0';
146
        return 0;
147
}