Branch data Line data Source code
1 : : /******************************************************************************
2 : : * Copyright (c) 2004, 2008 IBM Corporation
3 : : * All rights reserved.
4 : : * This program and the accompanying materials
5 : : * are made available under the terms of the BSD License
6 : : * which accompanies this distribution, and is available at
7 : : * http://www.opensource.org/licenses/bsd-license.php
8 : : *
9 : : * Contributors:
10 : : * IBM Corporation - initial implementation
11 : : *****************************************************************************/
12 : :
13 : : #include <stdbool.h>
14 : : #include <compiler.h>
15 : : #include "stdio.h"
16 : : #include "stdlib.h"
17 : : #include "string.h"
18 : : #include "ctype.h"
19 : :
20 : : static const unsigned long long convert[] = {
21 : : 0x0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF,
22 : : 0xFFFFFFFFFFULL, 0xFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL
23 : : };
24 : :
25 : : static int
26 : 2 : print_str_fill(char **buffer, size_t bufsize, char *sizec,
27 : : const char *str, char c)
28 : : {
29 : : size_t i, sizei, len;
30 : 2 : char *bstart = *buffer;
31 : :
32 : 2 : sizei = strtoul(sizec, NULL, 10);
33 : 2 : len = strlen(str);
34 : 2 : if (sizei > len) {
35 : 2 : for (i = 0;
36 : 590 : (i < (sizei - len)) && ((*buffer - bstart) < bufsize);
37 : 588 : i++) {
38 : 588 : **buffer = c;
39 : 588 : *buffer += 1;
40 : : }
41 : : }
42 : 2 : return 1;
43 : : }
44 : :
45 : : static int
46 : 12 : print_str(char **buffer, size_t bufsize, const char *str)
47 : : {
48 : 12 : char *bstart = *buffer;
49 : : size_t i;
50 : :
51 : 42 : for (i = 0; (i < strlen(str)) && ((*buffer - bstart) < bufsize); i++) {
52 : 30 : **buffer = str[i];
53 : 30 : *buffer += 1;
54 : : }
55 : 12 : return 1;
56 : : }
57 : :
58 : : static unsigned int __attrconst
59 : 3932 : print_intlen(unsigned long value, unsigned short int base)
60 : : {
61 : 3932 : int i = 0;
62 : :
63 : 13244 : while (value > 0) {
64 : 9312 : value /= base;
65 : 9312 : i++;
66 : : }
67 : 3932 : if (i == 0)
68 : 64 : i = 1;
69 : 3932 : return i;
70 : : }
71 : :
72 : : static int
73 : 691 : print_itoa(char **buffer, size_t bufsize, unsigned long value,
74 : : unsigned short base, bool upper)
75 : : {
76 : 691 : const char zeichen[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
77 : : char c;
78 : : int i, len;
79 : :
80 : 691 : if(base <= 2 || base > 16)
81 : 0 : return 0;
82 : :
83 : 691 : len = i = print_intlen(value, base);
84 : :
85 : : /* Don't print to buffer if bufsize is not enough. */
86 : 691 : if (len > bufsize)
87 : 75 : return 0;
88 : :
89 : : do {
90 : 3118 : c = zeichen[value % base];
91 : 3118 : if (upper)
92 : 360 : c = toupper(c);
93 : :
94 : 3118 : (*buffer)[--i] = c;
95 : 3118 : value /= base;
96 : 3118 : } while(value);
97 : :
98 : 616 : *buffer += len;
99 : :
100 : 616 : return 1;
101 : : }
102 : :
103 : :
104 : :
105 : : static int
106 : 3241 : print_fill(char **buffer, size_t bufsize, char *sizec, unsigned long size,
107 : : unsigned short int base, char c, int optlen)
108 : : {
109 : : int i, sizei, len;
110 : 3241 : char *bstart = *buffer;
111 : :
112 : 3241 : sizei = strtoul(sizec, NULL, 10);
113 : 3241 : len = print_intlen(size, base) + optlen;
114 : 3241 : if (sizei > len) {
115 : 84 : for (i = 0;
116 : 321 : (i < (sizei - len)) && ((*buffer - bstart) < bufsize);
117 : 237 : i++) {
118 : 237 : **buffer = c;
119 : 237 : *buffer += 1;
120 : : }
121 : : }
122 : :
123 : 3241 : return 0;
124 : : }
125 : :
126 : :
127 : : static int
128 : 3243 : print_format(char **buffer, size_t bufsize, const char *format, void *var)
129 : : {
130 : : char *start;
131 : 3243 : unsigned int i = 0, length_mod = sizeof(int);
132 : 3243 : unsigned long value = 0;
133 : : unsigned long signBit;
134 : : char *form, sizec[32];
135 : 3243 : char sign = ' ';
136 : 3243 : bool upper = false;
137 : :
138 : 3243 : form = (char *) format;
139 : 3243 : start = *buffer;
140 : :
141 : 3243 : form++;
142 : 3243 : if(*form == '0' || *form == '.') {
143 : 98 : sign = '0';
144 : 98 : form++;
145 : : }
146 : :
147 : 6726 : while ((*form != '\0') && ((*buffer - start) < bufsize)) {
148 : 3483 : switch(*form) {
149 : 511 : case 'u':
150 : : case 'd':
151 : : case 'i':
152 : 511 : sizec[i] = '\0';
153 : 511 : value = (unsigned long) var;
154 : 511 : signBit = 0x1ULL << (length_mod * 8 - 1);
155 : 511 : if ((*form != 'u') && (signBit & value)) {
156 : 120 : **buffer = '-';
157 : 120 : *buffer += 1;
158 : 120 : value = (-(unsigned long)value) & convert[length_mod];
159 : : }
160 : 511 : print_fill(buffer, bufsize - (*buffer - start),
161 : : sizec, value, 10, sign, 0);
162 : 511 : print_itoa(buffer, bufsize - (*buffer - start),
163 : : value, 10, upper);
164 : 511 : break;
165 : 80 : case 'X':
166 : 80 : upper = true;
167 : : /* fallthrough */
168 : 160 : case 'x':
169 : 160 : sizec[i] = '\0';
170 : 160 : value = (unsigned long) var & convert[length_mod];
171 : 160 : print_fill(buffer, bufsize - (*buffer - start),
172 : : sizec, value, 16, sign, 0);
173 : 160 : print_itoa(buffer, bufsize - (*buffer - start),
174 : : value, 16, upper);
175 : 160 : break;
176 : 10 : case 'O':
177 : : case 'o':
178 : 10 : sizec[i] = '\0';
179 : 10 : value = (long int) var & convert[length_mod];
180 : 10 : print_fill(buffer, bufsize - (*buffer - start),
181 : : sizec, value, 8, sign, 0);
182 : 10 : print_itoa(buffer, bufsize - (*buffer - start),
183 : : value, 8, upper);
184 : 10 : break;
185 : 10 : case 'p':
186 : 10 : sizec[i] = '\0';
187 : 10 : print_fill(buffer, bufsize - (*buffer - start),
188 : : sizec, (unsigned long) var, 16, ' ', 2);
189 : 10 : print_str(buffer, bufsize - (*buffer - start),
190 : : "0x");
191 : 10 : print_itoa(buffer, bufsize - (*buffer - start),
192 : : (unsigned long) var, 16, upper);
193 : 10 : break;
194 : 2550 : case 'c':
195 : 2550 : sizec[i] = '\0';
196 : 2550 : print_fill(buffer, bufsize - (*buffer - start),
197 : : sizec, 1, 10, ' ', 0);
198 : 2550 : **buffer = (unsigned long) var;
199 : 2550 : *buffer += 1;
200 : 2550 : break;
201 : 2 : case 's':
202 : 2 : sizec[i] = '\0';
203 : 2 : print_str_fill(buffer,
204 : 2 : bufsize - (*buffer - start), sizec,
205 : : (char *) var, ' ');
206 : :
207 : 2 : print_str(buffer, bufsize - (*buffer - start),
208 : : (char *) var);
209 : 2 : break;
210 : 18 : case 'l':
211 : 18 : form++;
212 : 18 : if(*form == 'l') {
213 : 0 : length_mod = sizeof(long long int);
214 : : } else {
215 : 18 : form--;
216 : 18 : length_mod = sizeof(long int);
217 : : }
218 : 18 : break;
219 : 70 : case 'h':
220 : 70 : form++;
221 : 70 : if(*form == 'h') {
222 : 0 : length_mod = sizeof(signed char);
223 : : } else {
224 : 70 : form--;
225 : 70 : length_mod = sizeof(short int);
226 : : }
227 : 70 : break;
228 : 40 : case 'z':
229 : 40 : length_mod = sizeof(size_t);
230 : 40 : break;
231 : 112 : default:
232 : 112 : if(*form >= '0' && *form <= '9')
233 : 112 : sizec[i++] = *form;
234 : : }
235 : 3483 : form++;
236 : : }
237 : :
238 : :
239 : 3243 : return (long int) (*buffer - start);
240 : : }
241 : :
242 : :
243 : : /*
244 : : * The vsnprintf function prints a formatted strings into a buffer.
245 : : * BUG: buffer size checking does not fully work yet
246 : : */
247 : : int
248 : 3246 : vsnprintf(char *buffer, size_t bufsize, const char *format, va_list arg)
249 : : {
250 : : char *ptr, *bstart;
251 : :
252 : 3246 : bstart = buffer;
253 : 3246 : ptr = (char *) format;
254 : :
255 : : /*
256 : : * Return from here if size passed is zero, otherwise we would
257 : : * overrun buffer while setting NULL character at the end.
258 : : */
259 : 3246 : if (!buffer || !bufsize)
260 : 0 : return 0;
261 : :
262 : : /* Leave one space for NULL character */
263 : 3246 : bufsize--;
264 : :
265 : 6701 : while(*ptr != '\0' && (buffer - bstart) < bufsize)
266 : : {
267 : 3455 : if(*ptr == '%') {
268 : : char formstr[20];
269 : 3248 : int i=0;
270 : :
271 : : do {
272 : 3586 : formstr[i] = *ptr;
273 : 3586 : ptr++;
274 : 3586 : i++;
275 : 3586 : } while(!(*ptr == 'd' || *ptr == 'i' || *ptr == 'u' || *ptr == 'x' || *ptr == 'X'
276 : 2915 : || *ptr == 'p' || *ptr == 'c' || *ptr == 's' || *ptr == '%'
277 : 348 : || *ptr == 'O' || *ptr == 'o' ));
278 : 3248 : formstr[i++] = *ptr;
279 : 3248 : formstr[i] = '\0';
280 : 3248 : if(*ptr == '%') {
281 : 5 : *buffer++ = '%';
282 : : } else {
283 : 3243 : print_format(&buffer,
284 : 3243 : bufsize - (buffer - bstart),
285 : : formstr, va_arg(arg, void *));
286 : : }
287 : 3248 : ptr++;
288 : : } else {
289 : :
290 : 207 : *buffer = *ptr;
291 : :
292 : 207 : buffer++;
293 : 207 : ptr++;
294 : : }
295 : : }
296 : :
297 : 3246 : *buffer = '\0';
298 : :
299 : 3246 : return (buffer - bstart);
300 : : }
|