Initial commit
[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 //------------------------------------------------------------------------------
43 // Local Definitions
44 //------------------------------------------------------------------------------
45
46 // Maximum string size allowed (in bytes).
47 #define MAX_STRING_SIZE 255
48
49 //------------------------------------------------------------------------------
50 // Global Variables
51 //------------------------------------------------------------------------------
52
53 // Required for proper compilation.
54 //struct _reent r = {0, (FILE*) 0, (FILE*) 1, (FILE*) 0};
55 //struct _reent *_impure_ptr = &r;
56
57 //------------------------------------------------------------------------------
58 // Local Functions
59 //------------------------------------------------------------------------------
60
61 //------------------------------------------------------------------------------
62 // Writes a character inside the given string. Returns 1.
63 // \param pStr Storage string.
64 // \param c Character to write.
65 //------------------------------------------------------------------------------
66 signed int append_char(char *pStr, char c)
67 {
68 *pStr = c;
69 return 1;
70 }
71
72 //------------------------------------------------------------------------------
73 // Writes a string inside the given string.
74 // Returns the size of the written
75 // string.
76 // \param pStr Storage string.
77 // \param pSource Source string.
78 //------------------------------------------------------------------------------
79 signed int PutString(char *pStr, char fill, signed int width, const char *pSource)
80 {
81 signed int num = 0;
82
83 while (*pSource != 0) {
84
85 *pStr++ = *pSource++;
86 num++;
87 }
88
89 width -= num;
90 while (width > 0) {
91
92 *pStr++ = fill;
93 num++;
94 width--;
95 }
96
97 return num;
98 }
99
100 //------------------------------------------------------------------------------
101 // Writes an unsigned int inside the given string, using the provided fill &
102 // width parameters.
103 // Returns the size in characters of the written integer.
104 // \param pStr Storage string.
105 // \param fill Fill character.
106 // \param width Minimum integer width.
107 // \param value Integer value.
108 //------------------------------------------------------------------------------
109 signed int PutUnsignedInt(
110 char *pStr,
111 char fill,
112 signed int width,
113 unsigned int value)
114 {
115 signed int num = 0;
116
117 // Take current digit into account when calculating width
118 width--;
119
120 // Recursively write upper digits
121 if ((value / 10) > 0) {
122
123 num = PutUnsignedInt(pStr, fill, width, value / 10);
124 pStr += num;
125 }
126 // Write filler characters
127 else {
128
129 while (width > 0) {
130
131 append_char(pStr, fill);
132 pStr++;
133 num++;
134 width--;
135 }
136 }
137
138 // Write lower digit
139 num += append_char(pStr, (value % 10) + '0');
140
141 return num;
142 }
143
144 //------------------------------------------------------------------------------
145 // Writes a signed int inside the given string, using the provided fill & width
146 // parameters.
147 // Returns the size of the written integer.
148 // \param pStr Storage string.
149 // \param fill Fill character.
150 // \param width Minimum integer width.
151 // \param value Signed integer value.
152 //------------------------------------------------------------------------------
153 signed int PutSignedInt(
154 char *pStr,
155 char fill,
156 signed int width,
157 signed int value)
158 {
159 signed int num = 0;
160 unsigned int absolute;
161
162 // Compute absolute value
163 if (value < 0) {
164
165 absolute = -value;
166 }
167 else {
168
169 absolute = value;
170 }
171
172 // Take current digit into account when calculating width
173 width--;
174
175 // Recursively write upper digits
176 if ((absolute / 10) > 0) {
177
178 if (value < 0) {
179
180 num = PutSignedInt(pStr, fill, width, -(absolute / 10));
181 }
182 else {
183
184 num = PutSignedInt(pStr, fill, width, absolute / 10);
185 }
186 pStr += num;
187 }
188 else {
189
190 // Reserve space for sign
191 if (value < 0) {
192
193 width--;
194 }
195
196 // Write filler characters
197 while (width > 0) {
198
199 append_char(pStr, fill);
200 pStr++;
201 num++;
202 width--;
203 }
204
205 // Write sign
206 if (value < 0) {
207
208 num += append_char(pStr, '-');
209 pStr++;
210 }
211 }
212
213 // Write lower digit
214 num += append_char(pStr, (absolute % 10) + '0');
215
216 return num;
217 }
218
219 //------------------------------------------------------------------------------
220 // Writes an hexadecimal value into a string, using the given fill, width &
221 // capital parameters.
222 // Returns the number of char written.
223 // \param pStr Storage string.
224 // \param fill Fill character.
225 // \param width Minimum integer width.
226 // \param maj Indicates if the letters must be printed in lower- or upper-case.
227 // \param value Hexadecimal value.
228 //------------------------------------------------------------------------------
229 signed int PutHexa(
230 char *pStr,
231 char fill,
232 signed int width,
233 unsigned char maj,
234 unsigned int value)
235 {
236 signed int num = 0;
237
238 // Decrement width
239 width--;
240
241 // Recursively output upper digits
242 if ((value >> 4) > 0) {
243
244 num += PutHexa(pStr, fill, width, maj, value >> 4);
245 pStr += num;
246 }
247 // Write filler chars
248 else {
249
250 while (width > 0) {
251
252 append_char(pStr, fill);
253 pStr++;
254 num++;
255 width--;
256 }
257 }
258
259 // Write current digit
260 if ((value & 0xF) < 10) {
261
262 append_char(pStr, (value & 0xF) + '0');
263 }
264 else if (maj) {
265
266 append_char(pStr, (value & 0xF) - 10 + 'A');
267 }
268 else {
269
270 append_char(pStr, (value & 0xF) - 10 + 'a');
271 }
272 num++;
273
274 return num;
275 }
276
277 //------------------------------------------------------------------------------
278 // Global Functions
279 //------------------------------------------------------------------------------
280
281 //------------------------------------------------------------------------------
282 /// Stores the result of a formatted string into another string. Format
283 /// arguments are given in a va_list instance.
284 /// Return the number of characters written.
285 /// \param pStr Destination string.
286 /// \param length Length of Destination string.
287 /// \param pFormat Format string.
288 /// \param ap Argument list.
289 //------------------------------------------------------------------------------
290 signed int vsnprintf(char *pStr, size_t length, const char *pFormat, va_list ap)
291 {
292 char fill;
293 unsigned char width;
294 signed int num = 0;
295 signed int size = 0;
296
297 // Clear the string
298 if (pStr) {
299
300 *pStr = 0;
301 }
302
303 // Phase string
304 while (*pFormat != 0 && size < length) {
305
306 // Normal character
307 if (*pFormat != '%') {
308
309 *pStr++ = *pFormat++;
310 size++;
311 }
312 // Escaped '%'
313 else if (*(pFormat+1) == '%') {
314
315 *pStr++ = '%';
316 pFormat += 2;
317 size++;
318 }
319 // Token delimiter
320 else {
321
322 fill = ' ';
323 width = 0;
324 pFormat++;
325
326 // Parse filler
327 if (*pFormat == '0') {
328
329 fill = '0';
330 pFormat++;
331 }
332
333 // Ignore justifier
334 if (*pFormat == '-') {
335 pFormat++;
336 }
337
338 // Parse width
339 while ((*pFormat >= '0') && (*pFormat <= '9')) {
340
341 width = (width*10) + *pFormat-'0';
342 pFormat++;
343 }
344
345 // Check if there is enough space
346 if (size + width > length) {
347
348 width = length - size;
349 }
350
351 // Parse type
352 switch (*pFormat) {
353 case 'd':
354 case 'i': num = PutSignedInt(pStr, fill, width, va_arg(ap, signed int)); break;
355 case 'u': num = PutUnsignedInt(pStr, fill, width, va_arg(ap, unsigned int)); break;
356 case 'x': num = PutHexa(pStr, fill, width, 0, va_arg(ap, unsigned int)); break;
357 case 'X': num = PutHexa(pStr, fill, width, 1, va_arg(ap, unsigned int)); break;
358 case 's': num = PutString(pStr, fill, width, va_arg(ap, char *)); break;
359 case 'c': num = append_char(pStr, va_arg(ap, unsigned int)); break;
360 default:
361 return EOF;
362 }
363
364 pFormat++;
365 pStr += num;
366 size += num;
367 }
368 }
369
370 // NULL-terminated (final \0 is not counted)
371 if (size < length) {
372
373 *pStr = 0;
374 }
375 else {
376
377 *(--pStr) = 0;
378 size--;
379 }
380
381 return size;
382 }
383
384 //------------------------------------------------------------------------------
385 /// Stores the result of a formatted string into another string. Format
386 /// arguments are given in a va_list instance.
387 /// Return the number of characters written.
388 /// \param pString Destination string.
389 /// \param length Length of Destination string.
390 /// \param pFormat Format string.
391 /// \param ... Other arguments
392 //------------------------------------------------------------------------------
393 signed int snprintf(char *pString, size_t length, const char *pFormat, ...)
394 {
395 va_list ap;
396 signed int rc;
397
398 va_start(ap, pFormat);
399 rc = vsnprintf(pString, length, pFormat, ap);
400 va_end(ap);
401
402 return rc;
403 }
404
405 //------------------------------------------------------------------------------
406 /// Stores the result of a formatted string into another string. Format
407 /// arguments are given in a va_list instance.
408 /// Return the number of characters written.
409 /// \param pString Destination string.
410 /// \param pFormat Format string.
411 /// \param ap Argument list.
412 //------------------------------------------------------------------------------
413 signed int vsprintf(char *pString, const char *pFormat, va_list ap)
414 {
415 return vsnprintf(pString, MAX_STRING_SIZE, pFormat, ap);
416 }
417
418 //------------------------------------------------------------------------------
419 /// Outputs a formatted string on the DBGU stream. Format arguments are given
420 /// in a va_list instance.
421 /// \param pFormat Format string
422 /// \param ap Argument list.
423 //------------------------------------------------------------------------------
424 signed int vprintf(const char *pFormat, va_list ap)
425 {
426 char pStr[MAX_STRING_SIZE];
427 char pError[] = "stdio.c: increase MAX_STRING_SIZE\r\n";
428
429 // Write formatted string in buffer
430 if (vsprintf(pStr, pFormat, ap) >= MAX_STRING_SIZE) {
431
432 puts(pError);
433 while (1); // Increase MAX_STRING_SIZE
434 }
435
436 // Display string
437 return puts(pStr);
438 }
439
440 //------------------------------------------------------------------------------
441 /// Outputs a formatted string on the DBGU stream, using a variable number of
442 /// arguments.
443 /// \param pFormat Format string.
444 //------------------------------------------------------------------------------
445 signed int printf(const char *pFormat, ...)
446 {
447 va_list ap;
448 signed int result;
449
450 // Forward call to vprintf
451 va_start(ap, pFormat);
452 result = vprintf(pFormat, ap);
453 va_end(ap);
454
455 return result;
456 }
457
458
459 //------------------------------------------------------------------------------
460 /// Writes a formatted string inside another string.
461 /// \param pStr Storage string.
462 /// \param pFormat Format string.
463 //------------------------------------------------------------------------------
464 signed int sprintf(char *pStr, const char *pFormat, ...)
465 {
466 va_list ap;
467 signed int result;
468
469 // Forward call to vsprintf
470 va_start(ap, pFormat);
471 result = vsprintf(pStr, pFormat, ap);
472 va_end(ap);
473
474 return result;
475 }
This page took 0.067668 seconds and 5 git commands to generate.