blob: 2bfaed7df179d9705bc8af4d9a2b2286ae7aafc9 [file] [log] [blame]
Harald Welted09829d2017-02-27 22:58:59 +01001/* ----------------------------------------------------------------------------
2 * ATMEL Microcontroller Software Support
3 * ----------------------------------------------------------------------------
4 * Copyright (c) 2008, Atmel Corporation
Kévin Redon1836ac02018-08-02 15:02:05 +02005 * Copyright (c) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
Harald Welted09829d2017-02-27 22:58:59 +01006 *
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 * - Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the disclaimer below.
14 *
15 * Atmel's name may not be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
21 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * ----------------------------------------------------------------------------
29 */
30
31//------------------------------------------------------------------------------
32/// \unit
33///
34/// !Purpose
35///
36/// Implementation of several stdio.h methods, such as printf(), sprintf() and
37/// so on. This reduces the memory footprint of the binary when using those
38/// methods, compared to the libc implementation.
39///
40/// !Usage
41///
42/// Adds stdio.c to the list of file to compile for the project. This will
43/// automatically replace libc methods by the custom ones.
44//------------------------------------------------------------------------------
45
46//------------------------------------------------------------------------------
47// Headers
48//------------------------------------------------------------------------------
49
50#include <stdio.h>
51#include <stdarg.h>
52
53//------------------------------------------------------------------------------
54// Local Definitions
55//------------------------------------------------------------------------------
56
57// Maximum string size allowed (in bytes).
Harald Welteee9ebb32017-03-02 16:52:08 +010058#define MAX_STRING_SIZE 512
Harald Welted09829d2017-02-27 22:58:59 +010059
60//------------------------------------------------------------------------------
61// Global Variables
62//------------------------------------------------------------------------------
Harald Weltec430ac12017-02-28 01:25:12 +010063//
64FILE* const stdin = NULL;
Harald Weltec3941092018-08-26 09:53:13 +020065/* If we use NULL here, we get compiler warnings of calling stdio functions with
66 * NULL values. Our fputs() implementation ignores the value of those pointers anyway */
67FILE* const stdout = (FILE *) 0x1;
68FILE* const stderr = (FILE *) 0x2;
Harald Welted09829d2017-02-27 22:58:59 +010069
Harald Welted09829d2017-02-27 22:58:59 +010070
71//------------------------------------------------------------------------------
72// Local Functions
73//------------------------------------------------------------------------------
74
75//------------------------------------------------------------------------------
76// Writes a character inside the given string. Returns 1.
77// \param pStr Storage string.
78// \param c Character to write.
79//------------------------------------------------------------------------------
80signed int PutChar(char *pStr, char c)
81{
Kévin Redon33d1eb72018-07-08 13:58:12 +020082 *pStr = c;
83 return 1;
Harald Welted09829d2017-02-27 22:58:59 +010084}
85
86//------------------------------------------------------------------------------
87// Writes a string inside the given string.
88// Returns the size of the written
89// string.
90// \param pStr Storage string.
91// \param pSource Source string.
92//------------------------------------------------------------------------------
93signed int PutString(char *pStr, const char *pSource)
94{
Kévin Redon33d1eb72018-07-08 13:58:12 +020095 signed int num = 0;
Harald Welted09829d2017-02-27 22:58:59 +010096
Kévin Redon33d1eb72018-07-08 13:58:12 +020097 while (*pSource != 0) {
Harald Welted09829d2017-02-27 22:58:59 +010098
Kévin Redon33d1eb72018-07-08 13:58:12 +020099 *pStr++ = *pSource++;
100 num++;
101 }
Harald Welted09829d2017-02-27 22:58:59 +0100102
Kévin Redon33d1eb72018-07-08 13:58:12 +0200103 return num;
Harald Welted09829d2017-02-27 22:58:59 +0100104}
105
106//------------------------------------------------------------------------------
107// Writes an unsigned int inside the given string, using the provided fill &
108// width parameters.
109// Returns the size in characters of the written integer.
110// \param pStr Storage string.
111// \param fill Fill character.
112// \param width Minimum integer width.
113// \param value Integer value.
114//------------------------------------------------------------------------------
115signed int PutUnsignedInt(
Kévin Redon33d1eb72018-07-08 13:58:12 +0200116 char *pStr,
117 char fill,
118 signed int width,
119 unsigned int value)
Harald Welted09829d2017-02-27 22:58:59 +0100120{
Kévin Redon33d1eb72018-07-08 13:58:12 +0200121 signed int num = 0;
Harald Welted09829d2017-02-27 22:58:59 +0100122
Kévin Redon33d1eb72018-07-08 13:58:12 +0200123 // Take current digit into account when calculating width
124 width--;
Harald Welted09829d2017-02-27 22:58:59 +0100125
Kévin Redon33d1eb72018-07-08 13:58:12 +0200126 // Recursively write upper digits
127 if ((value / 10) > 0) {
Harald Welted09829d2017-02-27 22:58:59 +0100128
Kévin Redon33d1eb72018-07-08 13:58:12 +0200129 num = PutUnsignedInt(pStr, fill, width, value / 10);
130 pStr += num;
131 }
132 // Write filler characters
133 else {
Harald Welted09829d2017-02-27 22:58:59 +0100134
Kévin Redon33d1eb72018-07-08 13:58:12 +0200135 while (width > 0) {
Harald Welted09829d2017-02-27 22:58:59 +0100136
Kévin Redon33d1eb72018-07-08 13:58:12 +0200137 PutChar(pStr, fill);
138 pStr++;
139 num++;
140 width--;
141 }
142 }
Harald Welted09829d2017-02-27 22:58:59 +0100143
Kévin Redon33d1eb72018-07-08 13:58:12 +0200144 // Write lower digit
145 num += PutChar(pStr, (value % 10) + '0');
Harald Welted09829d2017-02-27 22:58:59 +0100146
Kévin Redon33d1eb72018-07-08 13:58:12 +0200147 return num;
Harald Welted09829d2017-02-27 22:58:59 +0100148}
149
150//------------------------------------------------------------------------------
151// Writes a signed int inside the given string, using the provided fill & width
152// parameters.
153// Returns the size of the written integer.
154// \param pStr Storage string.
155// \param fill Fill character.
156// \param width Minimum integer width.
157// \param value Signed integer value.
158//------------------------------------------------------------------------------
159signed int PutSignedInt(
Kévin Redon33d1eb72018-07-08 13:58:12 +0200160 char *pStr,
161 char fill,
162 signed int width,
163 signed int value)
Harald Welted09829d2017-02-27 22:58:59 +0100164{
Kévin Redon33d1eb72018-07-08 13:58:12 +0200165 signed int num = 0;
166 unsigned int absolute;
Harald Welted09829d2017-02-27 22:58:59 +0100167
Kévin Redon33d1eb72018-07-08 13:58:12 +0200168 // Compute absolute value
169 if (value < 0) {
Harald Welted09829d2017-02-27 22:58:59 +0100170
Kévin Redon33d1eb72018-07-08 13:58:12 +0200171 absolute = -value;
172 }
173 else {
Harald Welted09829d2017-02-27 22:58:59 +0100174
Kévin Redon33d1eb72018-07-08 13:58:12 +0200175 absolute = value;
176 }
Harald Welted09829d2017-02-27 22:58:59 +0100177
Kévin Redon33d1eb72018-07-08 13:58:12 +0200178 // Take current digit into account when calculating width
179 width--;
Harald Welted09829d2017-02-27 22:58:59 +0100180
Kévin Redon33d1eb72018-07-08 13:58:12 +0200181 // Recursively write upper digits
182 if ((absolute / 10) > 0) {
Harald Welted09829d2017-02-27 22:58:59 +0100183
Kévin Redon33d1eb72018-07-08 13:58:12 +0200184 if (value < 0) {
185
186 num = PutSignedInt(pStr, fill, width, -(absolute / 10));
187 }
188 else {
Harald Welted09829d2017-02-27 22:58:59 +0100189
Kévin Redon33d1eb72018-07-08 13:58:12 +0200190 num = PutSignedInt(pStr, fill, width, absolute / 10);
191 }
192 pStr += num;
193 }
194 else {
Harald Welted09829d2017-02-27 22:58:59 +0100195
Kévin Redon33d1eb72018-07-08 13:58:12 +0200196 // Reserve space for sign
197 if (value < 0) {
Harald Welted09829d2017-02-27 22:58:59 +0100198
Kévin Redon33d1eb72018-07-08 13:58:12 +0200199 width--;
200 }
Harald Welted09829d2017-02-27 22:58:59 +0100201
Kévin Redon33d1eb72018-07-08 13:58:12 +0200202 // Write filler characters
203 while (width > 0) {
Harald Welted09829d2017-02-27 22:58:59 +0100204
Kévin Redon33d1eb72018-07-08 13:58:12 +0200205 PutChar(pStr, fill);
206 pStr++;
207 num++;
208 width--;
209 }
Harald Welted09829d2017-02-27 22:58:59 +0100210
Kévin Redon33d1eb72018-07-08 13:58:12 +0200211 // Write sign
212 if (value < 0) {
Harald Welted09829d2017-02-27 22:58:59 +0100213
Kévin Redon33d1eb72018-07-08 13:58:12 +0200214 num += PutChar(pStr, '-');
215 pStr++;
216 }
217 }
Harald Welted09829d2017-02-27 22:58:59 +0100218
Kévin Redon33d1eb72018-07-08 13:58:12 +0200219 // Write lower digit
220 num += PutChar(pStr, (absolute % 10) + '0');
Harald Welted09829d2017-02-27 22:58:59 +0100221
Kévin Redon33d1eb72018-07-08 13:58:12 +0200222 return num;
Harald Welted09829d2017-02-27 22:58:59 +0100223}
224
225//------------------------------------------------------------------------------
226// Writes an hexadecimal value into a string, using the given fill, width &
227// capital parameters.
228// Returns the number of char written.
229// \param pStr Storage string.
230// \param fill Fill character.
231// \param width Minimum integer width.
232// \param maj Indicates if the letters must be printed in lower- or upper-case.
233// \param value Hexadecimal value.
234//------------------------------------------------------------------------------
235signed int PutHexa(
Kévin Redon33d1eb72018-07-08 13:58:12 +0200236 char *pStr,
237 char fill,
238 signed int width,
239 unsigned char maj,
240 unsigned int value)
Harald Welted09829d2017-02-27 22:58:59 +0100241{
Kévin Redon33d1eb72018-07-08 13:58:12 +0200242 signed int num = 0;
Harald Welted09829d2017-02-27 22:58:59 +0100243
Kévin Redon33d1eb72018-07-08 13:58:12 +0200244 // Decrement width
245 width--;
Harald Welted09829d2017-02-27 22:58:59 +0100246
Kévin Redon33d1eb72018-07-08 13:58:12 +0200247 // Recursively output upper digits
248 if ((value >> 4) > 0) {
Harald Welted09829d2017-02-27 22:58:59 +0100249
Kévin Redon33d1eb72018-07-08 13:58:12 +0200250 num += PutHexa(pStr, fill, width, maj, value >> 4);
251 pStr += num;
252 }
253 // Write filler chars
254 else {
Harald Welted09829d2017-02-27 22:58:59 +0100255
Kévin Redon33d1eb72018-07-08 13:58:12 +0200256 while (width > 0) {
Harald Welted09829d2017-02-27 22:58:59 +0100257
Kévin Redon33d1eb72018-07-08 13:58:12 +0200258 PutChar(pStr, fill);
259 pStr++;
260 num++;
261 width--;
262 }
263 }
Harald Welted09829d2017-02-27 22:58:59 +0100264
Kévin Redon33d1eb72018-07-08 13:58:12 +0200265 // Write current digit
266 if ((value & 0xF) < 10) {
Harald Welted09829d2017-02-27 22:58:59 +0100267
Kévin Redon33d1eb72018-07-08 13:58:12 +0200268 PutChar(pStr, (value & 0xF) + '0');
269 }
270 else if (maj) {
Harald Welted09829d2017-02-27 22:58:59 +0100271
Kévin Redon33d1eb72018-07-08 13:58:12 +0200272 PutChar(pStr, (value & 0xF) - 10 + 'A');
273 }
274 else {
Harald Welted09829d2017-02-27 22:58:59 +0100275
Kévin Redon33d1eb72018-07-08 13:58:12 +0200276 PutChar(pStr, (value & 0xF) - 10 + 'a');
277 }
278 num++;
Harald Welted09829d2017-02-27 22:58:59 +0100279
Kévin Redon33d1eb72018-07-08 13:58:12 +0200280 return num;
Harald Welted09829d2017-02-27 22:58:59 +0100281}
282
283//------------------------------------------------------------------------------
284// Global Functions
285//------------------------------------------------------------------------------
286
287//------------------------------------------------------------------------------
288/// Stores the result of a formatted string into another string. Format
289/// arguments are given in a va_list instance.
290/// Return the number of characters written.
291/// \param pStr Destination string.
292/// \param length Length of Destination string.
293/// \param pFormat Format string.
294/// \param ap Argument list.
295//------------------------------------------------------------------------------
296signed int vsnprintf(char *pStr, size_t length, const char *pFormat, va_list ap)
297{
Kévin Redon33d1eb72018-07-08 13:58:12 +0200298 char fill;
299 unsigned char width;
300 signed int num = 0;
301 size_t size = 0;
Harald Welted09829d2017-02-27 22:58:59 +0100302
Kévin Redon33d1eb72018-07-08 13:58:12 +0200303 // Clear the string
304 if (pStr) {
Harald Welted09829d2017-02-27 22:58:59 +0100305
Kévin Redon33d1eb72018-07-08 13:58:12 +0200306 *pStr = 0;
307 }
Harald Welted09829d2017-02-27 22:58:59 +0100308
Kévin Redon33d1eb72018-07-08 13:58:12 +0200309 // Phase string
310 while (*pFormat != 0 && size < length) {
Harald Welted09829d2017-02-27 22:58:59 +0100311
Kévin Redon33d1eb72018-07-08 13:58:12 +0200312 // Normal character
313 if (*pFormat != '%') {
Harald Welted09829d2017-02-27 22:58:59 +0100314
Kévin Redon33d1eb72018-07-08 13:58:12 +0200315 *pStr++ = *pFormat++;
316 size++;
317 }
318 // Escaped '%'
319 else if (*(pFormat+1) == '%') {
Harald Welted09829d2017-02-27 22:58:59 +0100320
Kévin Redon33d1eb72018-07-08 13:58:12 +0200321 *pStr++ = '%';
322 pFormat += 2;
323 size++;
324 }
325 // Token delimiter
326 else {
Harald Welted09829d2017-02-27 22:58:59 +0100327
Kévin Redon33d1eb72018-07-08 13:58:12 +0200328 fill = ' ';
329 width = 0;
330 pFormat++;
Harald Welted09829d2017-02-27 22:58:59 +0100331
Kévin Redon33d1eb72018-07-08 13:58:12 +0200332 // Parse filler
333 if (*pFormat == '0') {
Harald Welted09829d2017-02-27 22:58:59 +0100334
Kévin Redon33d1eb72018-07-08 13:58:12 +0200335 fill = '0';
336 pFormat++;
337 }
Harald Welted09829d2017-02-27 22:58:59 +0100338
Kévin Redon33d1eb72018-07-08 13:58:12 +0200339 // Parse width
340 while ((*pFormat >= '0') && (*pFormat <= '9')) {
341
342 width = (width*10) + *pFormat-'0';
343 pFormat++;
344 }
Harald Welted09829d2017-02-27 22:58:59 +0100345
Kévin Redon33d1eb72018-07-08 13:58:12 +0200346 // Check if there is enough space
347 if (size + width > length) {
Harald Welted09829d2017-02-27 22:58:59 +0100348
Kévin Redon33d1eb72018-07-08 13:58:12 +0200349 width = length - size;
350 }
351
352 // Parse type
Kévin Redon29200c62018-08-28 19:36:58 +0200353 do {
354 num = 0;
355 switch (*pFormat) {
356 case 'l': num = -1; break; // ignore long qualifier since int == long (and long long is not supported)
357 case 'd':
358 case 'i': num = PutSignedInt(pStr, fill, width, va_arg(ap, signed int)); break;
359 case 'u': num = PutUnsignedInt(pStr, fill, width, va_arg(ap, unsigned int)); break;
360 case 'x': num = PutHexa(pStr, fill, width, 0, va_arg(ap, unsigned int)); break;
361 case 'X': num = PutHexa(pStr, fill, width, 1, va_arg(ap, unsigned int)); break;
362 case 's': num = PutString(pStr, va_arg(ap, char *)); break;
363 case 'c': num = PutChar(pStr, va_arg(ap, unsigned int)); break;
364 default:
365 return EOF;
366 }
367 pFormat++;
368 } while (num < 0);
Kévin Redon33d1eb72018-07-08 13:58:12 +0200369 pStr += num;
370 size += num;
371 }
372 }
Harald Welted09829d2017-02-27 22:58:59 +0100373
Kévin Redon33d1eb72018-07-08 13:58:12 +0200374 // NULL-terminated (final \0 is not counted)
375 if (size < length) {
Harald Welted09829d2017-02-27 22:58:59 +0100376
Kévin Redon33d1eb72018-07-08 13:58:12 +0200377 *pStr = 0;
378 }
379 else {
Harald Welted09829d2017-02-27 22:58:59 +0100380
Kévin Redon33d1eb72018-07-08 13:58:12 +0200381 *(--pStr) = 0;
382 size--;
383 }
Harald Welted09829d2017-02-27 22:58:59 +0100384
Kévin Redon33d1eb72018-07-08 13:58:12 +0200385 return size;
Harald Welted09829d2017-02-27 22:58:59 +0100386}
387
388//------------------------------------------------------------------------------
389/// Stores the result of a formatted string into another string. Format
390/// arguments are given in a va_list instance.
391/// Return the number of characters written.
392/// \param pString Destination string.
393/// \param length Length of Destination string.
394/// \param pFormat Format string.
395/// \param ... Other arguments
396//------------------------------------------------------------------------------
397signed int snprintf(char *pString, size_t length, const char *pFormat, ...)
398{
Kévin Redon33d1eb72018-07-08 13:58:12 +0200399 va_list ap;
400 signed int rc;
Harald Welted09829d2017-02-27 22:58:59 +0100401
Kévin Redon33d1eb72018-07-08 13:58:12 +0200402 va_start(ap, pFormat);
403 rc = vsnprintf(pString, length, pFormat, ap);
404 va_end(ap);
Harald Welted09829d2017-02-27 22:58:59 +0100405
Kévin Redon33d1eb72018-07-08 13:58:12 +0200406 return rc;
Harald Welted09829d2017-02-27 22:58:59 +0100407}
408
409//------------------------------------------------------------------------------
410/// Stores the result of a formatted string into another string. Format
411/// arguments are given in a va_list instance.
412/// Return the number of characters written.
413/// \param pString Destination string.
414/// \param pFormat Format string.
415/// \param ap Argument list.
416//------------------------------------------------------------------------------
417signed int vsprintf(char *pString, const char *pFormat, va_list ap)
418{
Kévin Redon33d1eb72018-07-08 13:58:12 +0200419 return vsnprintf(pString, MAX_STRING_SIZE, pFormat, ap);
Harald Welted09829d2017-02-27 22:58:59 +0100420}
421
422//------------------------------------------------------------------------------
423/// Outputs a formatted string on the given stream. Format arguments are given
424/// in a va_list instance.
425/// \param pStream Output stream.
426/// \param pFormat Format string
427/// \param ap Argument list.
428//------------------------------------------------------------------------------
429signed int vfprintf(FILE *pStream, const char *pFormat, va_list ap)
430{
Kévin Redon33d1eb72018-07-08 13:58:12 +0200431 char pStr[MAX_STRING_SIZE];
432 char pError[] = "stdio.c: increase MAX_STRING_SIZE\n\r";
Harald Welted09829d2017-02-27 22:58:59 +0100433
Kévin Redon33d1eb72018-07-08 13:58:12 +0200434 // Write formatted string in buffer
435 if (vsprintf(pStr, pFormat, ap) >= MAX_STRING_SIZE) {
Harald Welted09829d2017-02-27 22:58:59 +0100436
Kévin Redon33d1eb72018-07-08 13:58:12 +0200437 fputs(pError, stderr);
438 }
Harald Welted09829d2017-02-27 22:58:59 +0100439
Kévin Redon33d1eb72018-07-08 13:58:12 +0200440 // Display string
441 return fputs(pStr, pStream);
Harald Welted09829d2017-02-27 22:58:59 +0100442}
443
444//------------------------------------------------------------------------------
Kévin Redon1836ac02018-08-02 15:02:05 +0200445/// Outputs a formatted string on the given stream. Format arguments are given
446/// in a va_list instance.
447/// \note This function is synchronous (i.e. blocks until the print completes)
448/// \param pStream Output stream.
449/// \param pFormat Format string
450/// \param ap Argument list.
451//------------------------------------------------------------------------------
452#pragma GCC diagnostic push
453#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
454signed int vfprintf_sync(FILE *pStream, const char *pFormat, va_list ap)
455{
456 char pStr[MAX_STRING_SIZE];
457 char pError[] = "stdio.c: increase MAX_STRING_SIZE\n\r";
458
459 // Write formatted string in buffer
460 if (vsprintf(pStr, pFormat, ap) >= MAX_STRING_SIZE) {
461
462 fputs_sync(pError, stderr);
463 }
464
465 // Display string
466 return fputs_sync(pStr, pStream);
467}
468#pragma GCC diagnostic pop
469
470//------------------------------------------------------------------------------
Harald Welted09829d2017-02-27 22:58:59 +0100471/// Outputs a formatted string on the DBGU stream. Format arguments are given
472/// in a va_list instance.
473/// \param pFormat Format string
474/// \param ap Argument list.
475//------------------------------------------------------------------------------
476signed int vprintf(const char *pFormat, va_list ap)
477{
Kévin Redon33d1eb72018-07-08 13:58:12 +0200478 return vfprintf(stdout, pFormat, ap);
Harald Welted09829d2017-02-27 22:58:59 +0100479}
480
481//------------------------------------------------------------------------------
Kévin Redon1836ac02018-08-02 15:02:05 +0200482/// Outputs a formatted string on the DBGU stream. Format arguments are given
483/// in a va_list instance.
484/// \note This function is synchronous (i.e. blocks until the print completes)
485/// \param pFormat Format string
486/// \param ap Argument list.
487//------------------------------------------------------------------------------
488signed int vprintf_sync(const char *pFormat, va_list ap)
489{
490 return vfprintf_sync(stdout, pFormat, ap);
491}
492
493//------------------------------------------------------------------------------
Harald Welted09829d2017-02-27 22:58:59 +0100494/// Outputs a formatted string on the given stream, using a variable number of
495/// arguments.
496/// \param pStream Output stream.
497/// \param pFormat Format string.
498//------------------------------------------------------------------------------
499signed int fprintf(FILE *pStream, const char *pFormat, ...)
500{
Kévin Redon33d1eb72018-07-08 13:58:12 +0200501 va_list ap;
502 signed int result;
Harald Welted09829d2017-02-27 22:58:59 +0100503
Kévin Redon33d1eb72018-07-08 13:58:12 +0200504 // Forward call to vfprintf
505 va_start(ap, pFormat);
506 result = vfprintf(pStream, pFormat, ap);
507 va_end(ap);
Harald Welted09829d2017-02-27 22:58:59 +0100508
Kévin Redon33d1eb72018-07-08 13:58:12 +0200509 return result;
Harald Welted09829d2017-02-27 22:58:59 +0100510}
511
512//------------------------------------------------------------------------------
513/// Outputs a formatted string on the DBGU stream, using a variable number of
514/// arguments.
515/// \param pFormat Format string.
516//------------------------------------------------------------------------------
517signed int printf(const char *pFormat, ...)
518{
Kévin Redon33d1eb72018-07-08 13:58:12 +0200519 va_list ap;
520 signed int result;
Harald Welted09829d2017-02-27 22:58:59 +0100521
Kévin Redon33d1eb72018-07-08 13:58:12 +0200522 // Forward call to vprintf
523 va_start(ap, pFormat);
524 result = vprintf(pFormat, ap);
525 va_end(ap);
Harald Welted09829d2017-02-27 22:58:59 +0100526
Kévin Redon33d1eb72018-07-08 13:58:12 +0200527 return result;
Harald Welted09829d2017-02-27 22:58:59 +0100528}
529
530//------------------------------------------------------------------------------
Kévin Redon1836ac02018-08-02 15:02:05 +0200531/// Outputs a formatted string on the DBGU stream, using a variable number of
532/// arguments.
533/// \note This function is synchronous (i.e. blocks until the print completes)
534/// \param pFormat Format string.
535//------------------------------------------------------------------------------
536signed int printf_sync(const char *pFormat, ...)
537{
538 va_list ap;
539 signed int result;
540
541 // Forward call to vprintf
542 va_start(ap, pFormat);
543 result = vprintf_sync(pFormat, ap);
544 va_end(ap);
545
546 return result;
547}
548
549//------------------------------------------------------------------------------
Harald Welted09829d2017-02-27 22:58:59 +0100550/// Writes a formatted string inside another string.
551/// \param pStr Storage string.
552/// \param pFormat Format string.
553//------------------------------------------------------------------------------
554signed int sprintf(char *pStr, const char *pFormat, ...)
555{
Kévin Redon33d1eb72018-07-08 13:58:12 +0200556 va_list ap;
557 signed int result;
Harald Welted09829d2017-02-27 22:58:59 +0100558
Kévin Redon33d1eb72018-07-08 13:58:12 +0200559 // Forward call to vsprintf
560 va_start(ap, pFormat);
561 result = vsprintf(pStr, pFormat, ap);
562 va_end(ap);
Harald Welted09829d2017-02-27 22:58:59 +0100563
Kévin Redon33d1eb72018-07-08 13:58:12 +0200564 return result;
Harald Welted09829d2017-02-27 22:58:59 +0100565}
566
567//------------------------------------------------------------------------------
568/// Outputs a string on stdout.
569/// \param pStr String to output.
570//------------------------------------------------------------------------------
571signed int puts(const char *pStr)
572{
Kévin Redon33d1eb72018-07-08 13:58:12 +0200573 return fputs(pStr, stdout);
Harald Welted09829d2017-02-27 22:58:59 +0100574}
575