blob: 1002c2df6816ab30ba5768ae5a0815aa81c8c6e7 [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;
Harald Welte37055b92019-12-14 11:46:09 +0100361 case 'p': num = PutHexa(pStr, fill, width, 0, va_arg(ap, unsigned long)); break;
Kévin Redon29200c62018-08-28 19:36:58 +0200362 case 'X': num = PutHexa(pStr, fill, width, 1, va_arg(ap, unsigned int)); break;
363 case 's': num = PutString(pStr, va_arg(ap, char *)); break;
364 case 'c': num = PutChar(pStr, va_arg(ap, unsigned int)); break;
365 default:
366 return EOF;
367 }
368 pFormat++;
369 } while (num < 0);
Kévin Redon33d1eb72018-07-08 13:58:12 +0200370 pStr += num;
371 size += num;
372 }
373 }
Harald Welted09829d2017-02-27 22:58:59 +0100374
Kévin Redon33d1eb72018-07-08 13:58:12 +0200375 // NULL-terminated (final \0 is not counted)
376 if (size < length) {
Harald Welted09829d2017-02-27 22:58:59 +0100377
Kévin Redon33d1eb72018-07-08 13:58:12 +0200378 *pStr = 0;
379 }
380 else {
Harald Welted09829d2017-02-27 22:58:59 +0100381
Kévin Redon33d1eb72018-07-08 13:58:12 +0200382 *(--pStr) = 0;
383 size--;
384 }
Harald Welted09829d2017-02-27 22:58:59 +0100385
Kévin Redon33d1eb72018-07-08 13:58:12 +0200386 return size;
Harald Welted09829d2017-02-27 22:58:59 +0100387}
388
389//------------------------------------------------------------------------------
390/// Stores the result of a formatted string into another string. Format
391/// arguments are given in a va_list instance.
392/// Return the number of characters written.
393/// \param pString Destination string.
394/// \param length Length of Destination string.
395/// \param pFormat Format string.
396/// \param ... Other arguments
397//------------------------------------------------------------------------------
398signed int snprintf(char *pString, size_t length, const char *pFormat, ...)
399{
Kévin Redon33d1eb72018-07-08 13:58:12 +0200400 va_list ap;
401 signed int rc;
Harald Welted09829d2017-02-27 22:58:59 +0100402
Kévin Redon33d1eb72018-07-08 13:58:12 +0200403 va_start(ap, pFormat);
404 rc = vsnprintf(pString, length, pFormat, ap);
405 va_end(ap);
Harald Welted09829d2017-02-27 22:58:59 +0100406
Kévin Redon33d1eb72018-07-08 13:58:12 +0200407 return rc;
Harald Welted09829d2017-02-27 22:58:59 +0100408}
409
410//------------------------------------------------------------------------------
411/// Stores the result of a formatted string into another string. Format
412/// arguments are given in a va_list instance.
413/// Return the number of characters written.
414/// \param pString Destination string.
415/// \param pFormat Format string.
416/// \param ap Argument list.
417//------------------------------------------------------------------------------
418signed int vsprintf(char *pString, const char *pFormat, va_list ap)
419{
Kévin Redon33d1eb72018-07-08 13:58:12 +0200420 return vsnprintf(pString, MAX_STRING_SIZE, pFormat, ap);
Harald Welted09829d2017-02-27 22:58:59 +0100421}
422
423//------------------------------------------------------------------------------
424/// Outputs a formatted string on the given stream. Format arguments are given
425/// in a va_list instance.
426/// \param pStream Output stream.
427/// \param pFormat Format string
428/// \param ap Argument list.
429//------------------------------------------------------------------------------
430signed int vfprintf(FILE *pStream, const char *pFormat, va_list ap)
431{
Kévin Redon33d1eb72018-07-08 13:58:12 +0200432 char pStr[MAX_STRING_SIZE];
Harald Welted09829d2017-02-27 22:58:59 +0100433
Kévin Redon33d1eb72018-07-08 13:58:12 +0200434 // Write formatted string in buffer
Kévin Redonc1711122018-08-28 19:27:34 +0200435 int rc = vsprintf(pStr, pFormat, ap);
436 if (rc < 0) {
437 fputs("format string error in ", stderr);
438 fputs(pFormat, stderr);
439 return rc;
440 }
441 if (rc >= MAX_STRING_SIZE) {
442 fputs("stdio.c: increase MAX_STRING_SIZE\n\r", stderr);
443 return rc;
Kévin Redon33d1eb72018-07-08 13:58:12 +0200444 }
Harald Welted09829d2017-02-27 22:58:59 +0100445
Kévin Redon33d1eb72018-07-08 13:58:12 +0200446 // Display string
447 return fputs(pStr, pStream);
Harald Welted09829d2017-02-27 22:58:59 +0100448}
449
450//------------------------------------------------------------------------------
Kévin Redon1836ac02018-08-02 15:02:05 +0200451/// Outputs a formatted string on the given stream. Format arguments are given
452/// in a va_list instance.
453/// \note This function is synchronous (i.e. blocks until the print completes)
454/// \param pStream Output stream.
455/// \param pFormat Format string
456/// \param ap Argument list.
457//------------------------------------------------------------------------------
458#pragma GCC diagnostic push
459#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
460signed int vfprintf_sync(FILE *pStream, const char *pFormat, va_list ap)
461{
462 char pStr[MAX_STRING_SIZE];
Kévin Redon1836ac02018-08-02 15:02:05 +0200463
464 // Write formatted string in buffer
Kévin Redonc1711122018-08-28 19:27:34 +0200465 int rc = vsprintf(pStr, pFormat, ap);
466 if (rc < 0) {
467 fputs_sync("format string error in ", stderr);
468 fputs_sync(pFormat, stderr);
469 return rc;
470 }
471 if (rc >= MAX_STRING_SIZE) {
472 fputs_sync("stdio.c: increase MAX_STRING_SIZE\n\r", stderr);
473 return rc;
Kévin Redon1836ac02018-08-02 15:02:05 +0200474 }
475
476 // Display string
477 return fputs_sync(pStr, pStream);
478}
479#pragma GCC diagnostic pop
480
481//------------------------------------------------------------------------------
Harald Welted09829d2017-02-27 22:58:59 +0100482/// Outputs a formatted string on the DBGU stream. Format arguments are given
483/// in a va_list instance.
484/// \param pFormat Format string
485/// \param ap Argument list.
486//------------------------------------------------------------------------------
487signed int vprintf(const char *pFormat, va_list ap)
488{
Kévin Redon33d1eb72018-07-08 13:58:12 +0200489 return vfprintf(stdout, pFormat, ap);
Harald Welted09829d2017-02-27 22:58:59 +0100490}
491
492//------------------------------------------------------------------------------
Kévin Redon1836ac02018-08-02 15:02:05 +0200493/// Outputs a formatted string on the DBGU stream. Format arguments are given
494/// in a va_list instance.
495/// \note This function is synchronous (i.e. blocks until the print completes)
496/// \param pFormat Format string
497/// \param ap Argument list.
498//------------------------------------------------------------------------------
499signed int vprintf_sync(const char *pFormat, va_list ap)
500{
501 return vfprintf_sync(stdout, pFormat, ap);
502}
503
504//------------------------------------------------------------------------------
Harald Welted09829d2017-02-27 22:58:59 +0100505/// Outputs a formatted string on the given stream, using a variable number of
506/// arguments.
507/// \param pStream Output stream.
508/// \param pFormat Format string.
509//------------------------------------------------------------------------------
510signed int fprintf(FILE *pStream, const char *pFormat, ...)
511{
Kévin Redon33d1eb72018-07-08 13:58:12 +0200512 va_list ap;
513 signed int result;
Harald Welted09829d2017-02-27 22:58:59 +0100514
Kévin Redon33d1eb72018-07-08 13:58:12 +0200515 // Forward call to vfprintf
516 va_start(ap, pFormat);
517 result = vfprintf(pStream, pFormat, ap);
518 va_end(ap);
Harald Welted09829d2017-02-27 22:58:59 +0100519
Kévin Redon33d1eb72018-07-08 13:58:12 +0200520 return result;
Harald Welted09829d2017-02-27 22:58:59 +0100521}
522
523//------------------------------------------------------------------------------
524/// Outputs a formatted string on the DBGU stream, using a variable number of
525/// arguments.
526/// \param pFormat Format string.
527//------------------------------------------------------------------------------
528signed int printf(const char *pFormat, ...)
529{
Kévin Redon33d1eb72018-07-08 13:58:12 +0200530 va_list ap;
531 signed int result;
Harald Welted09829d2017-02-27 22:58:59 +0100532
Kévin Redon33d1eb72018-07-08 13:58:12 +0200533 // Forward call to vprintf
534 va_start(ap, pFormat);
535 result = vprintf(pFormat, ap);
536 va_end(ap);
Harald Welted09829d2017-02-27 22:58:59 +0100537
Kévin Redon33d1eb72018-07-08 13:58:12 +0200538 return result;
Harald Welted09829d2017-02-27 22:58:59 +0100539}
540
541//------------------------------------------------------------------------------
Kévin Redon1836ac02018-08-02 15:02:05 +0200542/// Outputs a formatted string on the DBGU stream, using a variable number of
543/// arguments.
544/// \note This function is synchronous (i.e. blocks until the print completes)
545/// \param pFormat Format string.
546//------------------------------------------------------------------------------
547signed int printf_sync(const char *pFormat, ...)
548{
549 va_list ap;
550 signed int result;
551
552 // Forward call to vprintf
553 va_start(ap, pFormat);
554 result = vprintf_sync(pFormat, ap);
555 va_end(ap);
556
557 return result;
558}
559
560//------------------------------------------------------------------------------
Harald Welted09829d2017-02-27 22:58:59 +0100561/// Writes a formatted string inside another string.
562/// \param pStr Storage string.
563/// \param pFormat Format string.
564//------------------------------------------------------------------------------
565signed int sprintf(char *pStr, const char *pFormat, ...)
566{
Kévin Redon33d1eb72018-07-08 13:58:12 +0200567 va_list ap;
568 signed int result;
Harald Welted09829d2017-02-27 22:58:59 +0100569
Kévin Redon33d1eb72018-07-08 13:58:12 +0200570 // Forward call to vsprintf
571 va_start(ap, pFormat);
572 result = vsprintf(pStr, pFormat, ap);
573 va_end(ap);
Harald Welted09829d2017-02-27 22:58:59 +0100574
Kévin Redon33d1eb72018-07-08 13:58:12 +0200575 return result;
Harald Welted09829d2017-02-27 22:58:59 +0100576}
577
578//------------------------------------------------------------------------------
579/// Outputs a string on stdout.
580/// \param pStr String to output.
581//------------------------------------------------------------------------------
582signed int puts(const char *pStr)
583{
Kévin Redon33d1eb72018-07-08 13:58:12 +0200584 return fputs(pStr, stdout);
Harald Welted09829d2017-02-27 22:58:59 +0100585}
586