Add qemu 2.4.0
[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 "stdio.h"
14 #include "stdlib.h"
15 #include "string.h"
16
17 const static unsigned long long convert[] = {
18         0x0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF,
19         0xFFFFFFFFFFULL, 0xFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL
20 };
21
22
23
24 static int
25 print_itoa(char **buffer,unsigned long value, unsigned short int base)
26 {
27         const char zeichen[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
28         static char sign = 0;
29
30         if(base <= 2 || base > 16)
31                 return 0;
32
33         if(value < 0) {
34                 sign = 1;
35                 value *= -1;
36         }
37
38         if(value < base) {
39                 if(sign) {
40                         **buffer = '-';
41                         *buffer += 1;
42                         sign = 0;
43                 }
44                 **buffer = zeichen[value];
45                 *buffer += 1;
46         } else {
47                 print_itoa(buffer, value / base, base);
48                 **buffer = zeichen[(value % base)];
49                 *buffer += 1;
50         }
51
52         return 1;
53 }
54
55
56 static unsigned int
57 print_intlen(unsigned long value, unsigned short int base)
58 {
59         int i = 0;
60
61         while(value > 0) {
62                 value /= base;
63                 i++;
64         }
65         if(i == 0) i = 1;
66         return i;
67 }
68
69
70 static int
71 print_fill(char **buffer, char *sizec, unsigned long size, unsigned short int base, char c, int optlen)
72 {
73         int i, sizei, len;
74
75         sizei = strtoul(sizec, NULL, 10);
76         len = print_intlen(size, base) + optlen;
77         if(sizei > len) {
78                 for(i = 0; i < (sizei - len); i++) {
79                         **buffer = c;
80                         *buffer += 1;
81                 }
82         }
83
84         return 0;
85 }
86
87
88 static int
89 print_format(char **buffer, const char *format, void *var)
90 {
91         unsigned long start;
92         unsigned int i = 0, sizei = 0, len = 0, length_mod = sizeof(int);
93         unsigned long value = 0;
94         unsigned long signBit;
95         char *form, sizec[32];
96         char sign = ' ';
97
98         form  = (char *) format;
99         start = (unsigned long) *buffer;
100
101         form++;
102         if(*form == '0' || *form == '.') {
103                 sign = '0';
104                 form++;
105         }
106
107         while(*form != '\0') {
108                 switch(*form) {
109                         case 'u':
110                         case 'd':
111                         case 'i':
112                                 sizec[i] = '\0';
113                                 value = (unsigned long) var;
114                                 signBit = 0x1ULL << (length_mod * 8 - 1);
115                                 if (signBit & value) {
116                                         **buffer = '-';
117                                         *buffer += 1;
118                                         value = (-(unsigned long)value) & convert[length_mod];
119                                 }
120                                 print_fill(buffer, sizec, value, 10, sign, 0);
121                                 print_itoa(buffer, value, 10);
122                                 break;
123                         case 'X':
124                         case 'x':
125                                 sizec[i] = '\0';
126                                 value = (unsigned long) var & convert[length_mod];
127                                 print_fill(buffer, sizec, value, 16, sign, 0);
128                                 print_itoa(buffer, value, 16);
129                                 break;
130                         case 'O':
131                         case 'o':
132                                 sizec[i] = '\0';
133                                 value = (long int) var & convert[length_mod];
134                                 print_fill(buffer, sizec, value, 8, sign, 0);
135                                 print_itoa(buffer, value, 8);
136                                 break;
137                         case 'p':
138                                 sizec[i] = '\0';
139                                 print_fill(buffer, sizec, (unsigned long) var, 16, ' ', 2);
140                                 **buffer = '0';
141                                 *buffer += 1;   
142                                 **buffer = 'x';
143                                 *buffer += 1;
144                                 print_itoa(buffer,(unsigned long) var, 16);
145                                 break;
146                         case 'c':
147                                 sizec[i] = '\0';
148                                 print_fill(buffer, sizec, 1, 10, ' ', 0);
149                                 **buffer = (unsigned long) var;
150                                 *buffer += 1;
151                                 break;
152                         case 's':
153                                 sizec[i] = '\0';
154                                 sizei = strtoul(sizec, NULL, 10);
155                                 len = strlen((char *) var);
156                                 if(sizei > len) {
157                                         for(i = 0; i < (sizei - len); i++) {
158                                                 **buffer = ' ';
159                                                 *buffer += 1;
160                                         }
161                                 }
162                                 for(i = 0; i < strlen((char *) var); i++) {
163                                         **buffer = ((char *) var)[i];
164                                         *buffer += 1;
165                                 }
166                                 break;
167                         case 'l':
168                                 form++;
169                                 if(*form == 'l') {
170                                         length_mod = sizeof(long long int);
171                                 } else {
172                                         form--;
173                                         length_mod = sizeof(long int);
174                                 }
175                                 break;
176                         case 'h':
177                                 form++;
178                                 if(*form == 'h') {
179                                         length_mod = sizeof(signed char);
180                                 } else {
181                                         form--;
182                                         length_mod = sizeof(short int);
183                                 }
184                                 break;
185                         default:
186                                 if(*form >= '0' && *form <= '9')
187                                         sizec[i++] = *form;
188                 }
189                 form++;
190         }
191
192         
193         return (long int) (*buffer - start);
194 }
195
196
197 /*
198  * The vsnprintf function prints a formated strings into a buffer.
199  * BUG: buffer size checking does not fully work yet
200  */
201 int
202 vsnprintf(char *buffer, size_t bufsize, const char *format, va_list arg)
203 {
204         char *ptr, *bstart;
205
206         bstart = buffer;
207         ptr = (char *) format;
208
209         while(*ptr != '\0' && (buffer - bstart) < bufsize)
210         {
211                 if(*ptr == '%') {
212                         char formstr[20];
213                         int i=0;
214                         
215                         do {
216                                 formstr[i] = *ptr;
217                                 ptr++;
218                                 i++;
219                         } while(!(*ptr == 'd' || *ptr == 'i' || *ptr == 'u' || *ptr == 'x' || *ptr == 'X'
220                                                 || *ptr == 'p' || *ptr == 'c' || *ptr == 's' || *ptr == '%'
221                                                 || *ptr == 'O' || *ptr == 'o' )); 
222                         formstr[i++] = *ptr;
223                         formstr[i] = '\0';
224                         if(*ptr == '%') {
225                                 *buffer++ = '%';
226                         } else {
227                                 print_format(&buffer, formstr, va_arg(arg, void *));
228                         }
229                         ptr++;
230                 } else {
231
232                         *buffer = *ptr;
233
234                         buffer++;
235                         ptr++;
236                 }
237         }
238         
239         *buffer = '\0';
240
241         return (buffer - bstart);
242 }