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