Project

General

Profile

Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (3.88 KB)

1 03e9c04a Brad Neuman
/*-
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 <limits.h>
35
#include <stdarg.h>
36
#include <string.h>
37
#include <stdio.h>
38
39
#define isdigit(c)  ((unsigned)((c) - '0') < 10)
40
41
static int
42
divide(long *n, int base)
43
{
44
        int res;
45
46
        /*
47
         * Note: Optimized for ARM processor which does not support
48
         * divide instructions.
49
         *
50
         * res = ((unsigned long)*n) % (unsigned int)base;
51
         * *n = ((unsigned long)*n) / (unsigned int)base;
52
         */
53
54
        if (base == 10) {
55
                res = (int)(((unsigned long)*n) % 10U);
56
                *n = (long)(((unsigned long)*n) / 10U);
57
        } else {
58
                res = (int)(((unsigned long)*n) % 16U);
59
                *n = (long)(((unsigned long)*n) / 16U);
60
        }
61
        return res;
62
}
63
64
static int
65
atoi(const char **s)
66
{
67
        int i = 0;
68
        while (isdigit((int)**s))
69
                i = i * 10 + *((*s)++) - '0';
70
        return i;
71
}
72
73
/*
74
 * Print formatted output - scaled down version
75
 *
76
 * Identifiers:
77
 *  %d - Decimal signed int
78
 *  %x - Hex integer
79
 *  %u - Unsigned integer
80
 *  %c - Character
81
 *  %s - String
82
 *
83
 * Flags:
84
 *   0 - Zero pad
85
 */
86
int
87
vsprintf(char *buf, const char *fmt, va_list args)
88
{
89
        char *p, *str;
90
        const char *digits = "0123456789abcdef";
91
        char pad, tmp[16];
92
        int width, base, sign, i, size;
93
        long num;
94
95
        size = 0;
96
        for (p = buf; *fmt && (size < LINE_MAX); fmt++, size++) {
97
                if (*fmt != '%') {
98
                        *p++ = *fmt;
99
                        continue;
100
                }
101
                /* get flags */
102
                ++fmt;
103
                pad = ' ';
104
                if (*fmt == '0') {
105
                        pad = '0';
106
                        fmt++;
107
                }
108
                if (*fmt == 'l')
109
                        fmt++;
110
                /* get width */
111
                width = -1;
112
                if (isdigit((int)*fmt)) {
113
                        width = atoi(&fmt);
114
                }
115
                base = 10;
116
                sign = 0;
117
                switch (*fmt) {
118
                case 'c':
119
                        *p++ = (unsigned char)va_arg(args, int);
120
                        continue;
121
                case 's':
122
                        str = va_arg(args, char *);
123
                        if (str == NULL)
124
                                str = "<NULL>";
125
                        for (; *str; str++) {
126
                                *p++ = *str;
127
                                if (size++ >= LINE_MAX)
128
                                        break;
129
                        }
130
                        continue;
131
                case 'X':
132
                case 'x':
133
                        base = 16;
134
                        break;
135
                case 'd':
136
                        sign = 1;
137
                        break;
138
                case 'u':
139
                        break;
140
                default:
141
                        continue;
142
                }
143
                num = va_arg(args, long);
144
                if (sign && num < 0) {
145
                        num = -num;
146
                        *p++ = '-';
147
                        width--;
148
                }
149
                i = 0;
150
                if (num == 0)
151
                        tmp[i++] = '0';
152
                else
153
                        while (num != 0)
154
                                tmp[i++] = digits[divide(&num, base)];
155
                width -= i;
156
                while (width-- > 0)
157
                        *p++ = pad;
158
                while (i-- > 0)
159
                        *p++ = tmp[i];
160
        }
161
        *p = '\0';
162
        return (p - buf);
163
}
164
165
int
166
sprintf(char *buf, const char *fmt, ...)
167
{
168
        va_list args;
169
        int i;
170
171
        va_start(args, fmt);
172
        i = vsprintf(buf, fmt, args);
173
        va_end(args);
174
        return i;
175
}