Backport auf gcc 4.6
[hackover2013-badge-firmware.git] / core / libc / stdio.c
1 /*
2 * Software License Agreement (BSD License)
3 *
4 * Based on original stdio.c released by Atmel
5 * Copyright (c) 2008, Atmel Corporation
6 * All rights reserved.
7 *
8 * Modified by Roel Verdult, Copyright (c) 2010
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the copyright holders nor the
18 * names of its contributors may be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34 //------------------------------------------------------------------------------
35 // Headers
36 //------------------------------------------------------------------------------
37
38 #include <stdio.h>
39 #include <stdarg.h>
40 #include <stdint.h>
41
42 #include "projectconfig.h" // For CFG_PRINTF_MAXSTRINGSIZE
43
44 //------------------------------------------------------------------------------
45 // Global Variables
46 //------------------------------------------------------------------------------
47
48 // Required for proper compilation.
49 //struct _reent r = {0, (FILE*) 0, (FILE*) 1, (FILE*) 0};
50 //struct _reent *_impure_ptr = &r;
51
52 //------------------------------------------------------------------------------
53 // Local Functions
54 //------------------------------------------------------------------------------
55
56 //------------------------------------------------------------------------------
57 // Writes a character inside the given string. Returns 1.
58 // \param pStr Storage string.
59 // \param c Character to write.
60 //------------------------------------------------------------------------------
61 signed int append_char(char *pStr, char c)
62 {
63 *pStr = c;
64 return 1;
65 }
66
67 //------------------------------------------------------------------------------
68 // Writes a string inside the given string.
69 // Returns the size of the written
70 // string.
71 // \param pStr Storage string.
72 // \param pSource Source string.
73 //------------------------------------------------------------------------------
74 signed int PutString(char *pStr, char fill, signed int width, const char *pSource)
75 {
76 signed int num = 0;
77
78 while (*pSource != 0) {
79
80 *pStr++ = *pSource++;
81 num++;
82 }
83
84 width -= num;
85 while (width > 0) {
86
87 *pStr++ = fill;
88 num++;
89 width--;
90 }
91
92 return num;
93 }
94
95 //------------------------------------------------------------------------------
96 // Writes an unsigned int inside the given string, using the provided fill &
97 // width parameters.
98 // Returns the size in characters of the written integer.
99 // \param pStr Storage string.
100 // \param fill Fill character.
101 // \param width Minimum integer width.
102 // \param value Integer value.
103 //------------------------------------------------------------------------------
104 signed int PutUnsignedInt(
105 char *pStr,
106 char fill,
107 signed int width,
108 unsigned int value)
109 {
110 signed int num = 0;
111
112 // Take current digit into account when calculating width
113 width--;
114
115 // Recursively write upper digits
116 if ((value / 10) > 0) {
117
118 num = PutUnsignedInt(pStr, fill, width, value / 10);
119 pStr += num;
120 }
121 // Write filler characters
122 else {
123
124 while (width > 0) {
125
126 append_char(pStr, fill);
127 pStr++;
128 num++;
129 width--;
130 }
131 }
132
133 // Write lower digit
134 num += append_char(pStr, (value % 10) + '0');
135
136 return num;
137 }
138
139 //------------------------------------------------------------------------------
140 // Writes a signed int inside the given string, using the provided fill & width
141 // parameters.
142 // Returns the size of the written integer.
143 // \param pStr Storage string.
144 // \param fill Fill character.
145 // \param width Minimum integer width.
146 // \param value Signed integer value.
147 //------------------------------------------------------------------------------
148 signed int PutSignedInt(
149 char *pStr,
150 char fill,
151 signed int width,
152 signed int value)
153 {
154 signed int num = 0;
155 unsigned int absolute;
156
157 // Compute absolute value
158 if (value < 0) {
159
160 absolute = -value;
161 }
162 else {
163
164 absolute = value;
165 }
166
167 // Take current digit into account when calculating width
168 width--;
169
170 // Recursively write upper digits
171 if ((absolute / 10) > 0) {
172
173 if (value < 0) {
174
175 num = PutSignedInt(pStr, fill, width, -(absolute / 10));
176 }
177 else {
178
179 num = PutSignedInt(pStr, fill, width, absolute / 10);
180 }
181 pStr += num;
182 }
183 else {
184
185 // Reserve space for sign
186 if (value < 0) {
187
188 width--;
189 }
190
191 // Write filler characters
192 while (width > 0) {
193
194 append_char(pStr, fill);
195 pStr++;
196 num++;
197 width--;
198 }
199
200 // Write sign
201 if (value < 0) {
202
203 num += append_char(pStr, '-');
204 pStr++;
205 }
206 }
207
208 // Write lower digit
209 num += append_char(pStr, (absolute % 10) + '0');
210
211 return num;
212 }
213
214 //------------------------------------------------------------------------------
215 // Writes an hexadecimal value into a string, using the given fill, width &
216 // capital parameters.
217 // Returns the number of char written.
218 // \param pStr Storage string.
219 // \param fill Fill character.
220 // \param width Minimum integer width.
221 // \param maj Indicates if the letters must be printed in lower- or upper-case.
222 // \param value Hexadecimal value.
223 //------------------------------------------------------------------------------
224 signed int PutHexa(
225 char *pStr,
226 char fill,
227 signed int width,
228 unsigned char maj,
229 unsigned int value)
230 {
231 signed int num = 0;
232
233 // Decrement width
234 width--;
235
236 // Recursively output upper digits
237 if ((value >> 4) > 0) {
238
239 num += PutHexa(pStr, fill, width, maj, value >> 4);
240 pStr += num;
241 }
242 // Write filler chars
243 else {
244
245 while (width > 0) {
246
247 append_char(pStr, fill);
248 pStr++;
249 num++;
250 width--;
251 }
252 }
253
254 // Write current digit
255 if ((value & 0xF) < 10) {
256
257 append_char(pStr, (value & 0xF) + '0');
258 }
259 else if (maj) {
260
261 append_char(pStr, (value & 0xF) - 10 + 'A');
262 }
263 else {
264
265 append_char(pStr, (value & 0xF) - 10 + 'a');
266 }
267 num++;
268
269 return num;
270 }
271
272 //------------------------------------------------------------------------------
273 // Global Functions
274 //------------------------------------------------------------------------------
275
276 //------------------------------------------------------------------------------
277 /// Stores the result of a formatted string into another string. Format
278 /// arguments are given in a va_list instance.
279 /// Return the number of characters written.
280 /// \param pStr Destination string.
281 /// \param length Length of Destination string.
282 /// \param pFormat Format string.
283 /// \param ap Argument list.
284 //------------------------------------------------------------------------------
285 signed int vsnprintf(char *pStr, size_t length, const char *pFormat, va_list ap)
286 {
287 char fill;
288 unsigned char width;
289 signed int num = 0;
290 signed int size = 0;
291
292 // Clear the string
293 if (pStr) {
294
295 *pStr = 0;
296 }
297
298 // Phase string
299 while (*pFormat != 0 && size < length) {
300
301 // Normal character
302 if (*pFormat != '%') {
303
304 *pStr++ = *pFormat++;
305 size++;
306 }
307 // Escaped '%'
308 else if (*(pFormat+1) == '%') {
309
310 *pStr++ = '%';
311 pFormat += 2;
312 size++;
313 }
314 // Token delimiter
315 else {
316
317 fill = ' ';
318 width = 0;
319 pFormat++;
320
321 // Parse filler
322 if (*pFormat == '0') {
323
324 fill = '0';
325 pFormat++;
326 }
327
328 // Ignore justifier
329 if (*pFormat == '-') {
330 pFormat++;
331 }
332
333 // Parse width
334 while ((*pFormat >= '0') && (*pFormat <= '9')) {
335
336 width = (width*10) + *pFormat-'0';
337 pFormat++;
338 }
339
340 // Check if there is enough space
341 if (size + width > length) {
342
343 width = length - size;
344 }
345
346 // Parse type
347 switch (*pFormat) {
348 case 'd':
349 case 'i': num = PutSignedInt(pStr, fill, width, va_arg(ap, signed int)); break;
350 case 'u': num = PutUnsignedInt(pStr, fill, width, va_arg(ap, unsigned int)); break;
351 case 'x': num = PutHexa(pStr, fill, width, 0, va_arg(ap, unsigned int)); break;
352 case 'X': num = PutHexa(pStr, fill, width, 1, va_arg(ap, unsigned int)); break;
353 case 's': num = PutString(pStr, fill, width, va_arg(ap, char *)); break;
354 case 'c': num = append_char(pStr, va_arg(ap, unsigned int)); break;
355 default:
356 return EOF;
357 }
358
359 pFormat++;
360 pStr += num;
361 size += num;
362 }
363 }
364
365 // NULL-terminated (final \0 is not counted)
366 if (size < length) {
367
368 *pStr = 0;
369 }
370 else {
371
372 *(--pStr) = 0;
373 size--;
374 }
375
376 return size;
377 }
378
379 //------------------------------------------------------------------------------
380 /// Stores the result of a formatted string into another string. Format
381 /// arguments are given in a va_list instance.
382 /// Return the number of characters written.
383 /// \param pString Destination string.
384 /// \param length Length of Destination string.
385 /// \param pFormat Format string.
386 /// \param ... Other arguments
387 //------------------------------------------------------------------------------
388 signed int snprintf(char *pString, size_t length, const char *pFormat, ...)
389 {
390 va_list ap;
391 signed int rc;
392
393 va_start(ap, pFormat);
394 rc = vsnprintf(pString, length, pFormat, ap);
395 va_end(ap);
396
397 return rc;
398 }
399
400 //------------------------------------------------------------------------------
401 /// Stores the result of a formatted string into another string. Format
402 /// arguments are given in a va_list instance.
403 /// Return the number of characters written.
404 /// \param pString Destination string.
405 /// \param pFormat Format string.
406 /// \param ap Argument list.
407 //------------------------------------------------------------------------------
408 signed int vsprintf(char *pString, const char *pFormat, va_list ap)
409 {
410 return vsnprintf(pString, CFG_PRINTF_MAXSTRINGSIZE, pFormat, ap);
411 }
412
413 //------------------------------------------------------------------------------
414 /// Outputs a formatted string on the DBGU stream. Format arguments are given
415 /// in a va_list instance.
416 /// \param pFormat Format string
417 /// \param ap Argument list.
418 //------------------------------------------------------------------------------
419 signed int vprintf(const char *pFormat, va_list ap)
420 {
421 char pStr[CFG_PRINTF_MAXSTRINGSIZE];
422 char pError[] = "stdio.c: increase CFG_PRINTF_MAXSTRINGSIZE\r\n";
423
424 // Write formatted string in buffer
425 if (vsprintf(pStr, pFormat, ap) >= CFG_PRINTF_MAXSTRINGSIZE) {
426
427 puts(pError);
428 while (1); // Increase CFG_PRINTF_MAXSTRINGSIZE
429 }
430
431 // Display string
432 return puts(pStr);
433 }
434
435 //------------------------------------------------------------------------------
436 /// Outputs a formatted string on the DBGU stream, using a variable number of
437 /// arguments.
438 /// \param pFormat Format string.
439 //------------------------------------------------------------------------------
440 signed int printf(const char *pFormat, ...)
441 {
442 va_list ap;
443 signed int result;
444
445 // Forward call to vprintf
446 va_start(ap, pFormat);
447 result = vprintf(pFormat, ap);
448 va_end(ap);
449
450 return result;
451 }
452
453
454 //------------------------------------------------------------------------------
455 /// Writes a formatted string inside another string.
456 /// \param pStr Storage string.
457 /// \param pFormat Format string.
458 //------------------------------------------------------------------------------
459 signed int sprintf(char *pStr, const char *pFormat, ...)
460 {
461 va_list ap;
462 signed int result;
463
464 // Forward call to vsprintf
465 va_start(ap, pFormat);
466 result = vsprintf(pStr, pFormat, ap);
467 va_end(ap);
468
469 return result;
470 }
This page took 0.082732 seconds and 5 git commands to generate.