xref: /btstack/3rd-party/segger-rtt/SEGGER_RTT_printf.c (revision ce6f85e79d1d141c1b45dfa16b2671762457cbb4)
17dc86dfdSMatthias Ringwald /*********************************************************************
2779af47bSMatthias Ringwald *                    SEGGER Microcontroller GmbH                     *
3*ce6f85e7SMatthias Ringwald *                        The Embedded Experts                        *
47dc86dfdSMatthias Ringwald **********************************************************************
57dc86dfdSMatthias Ringwald *                                                                    *
6*ce6f85e7SMatthias Ringwald *            (c) 1995 - 2019 SEGGER Microcontroller GmbH             *
77dc86dfdSMatthias Ringwald *                                                                    *
87dc86dfdSMatthias Ringwald *       www.segger.com     Support: [email protected]               *
97dc86dfdSMatthias Ringwald *                                                                    *
107dc86dfdSMatthias Ringwald **********************************************************************
117dc86dfdSMatthias Ringwald *                                                                    *
127dc86dfdSMatthias Ringwald *       SEGGER RTT * Real Time Transfer for embedded targets         *
137dc86dfdSMatthias Ringwald *                                                                    *
147dc86dfdSMatthias Ringwald **********************************************************************
157dc86dfdSMatthias Ringwald *                                                                    *
167dc86dfdSMatthias Ringwald * All rights reserved.                                               *
177dc86dfdSMatthias Ringwald *                                                                    *
187dc86dfdSMatthias Ringwald * SEGGER strongly recommends to not make any changes                 *
197dc86dfdSMatthias Ringwald * to or modify the source code of this software in order to stay     *
207dc86dfdSMatthias Ringwald * compatible with the RTT protocol and J-Link.                       *
217dc86dfdSMatthias Ringwald *                                                                    *
227dc86dfdSMatthias Ringwald * Redistribution and use in source and binary forms, with or         *
237dc86dfdSMatthias Ringwald * without modification, are permitted provided that the following    *
24*ce6f85e7SMatthias Ringwald * condition is met:                                                  *
257dc86dfdSMatthias Ringwald *                                                                    *
267dc86dfdSMatthias Ringwald * o Redistributions of source code must retain the above copyright   *
27*ce6f85e7SMatthias Ringwald *   notice, this condition and the following disclaimer.             *
287dc86dfdSMatthias Ringwald *                                                                    *
297dc86dfdSMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND             *
307dc86dfdSMatthias Ringwald * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,        *
317dc86dfdSMatthias Ringwald * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF           *
327dc86dfdSMatthias Ringwald * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE           *
337dc86dfdSMatthias Ringwald * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
347dc86dfdSMatthias Ringwald * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR           *
357dc86dfdSMatthias Ringwald * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  *
367dc86dfdSMatthias Ringwald * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;    *
377dc86dfdSMatthias Ringwald * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF      *
387dc86dfdSMatthias Ringwald * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT          *
397dc86dfdSMatthias Ringwald * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE  *
407dc86dfdSMatthias Ringwald * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   *
417dc86dfdSMatthias Ringwald * DAMAGE.                                                            *
427dc86dfdSMatthias Ringwald *                                                                    *
437dc86dfdSMatthias Ringwald **********************************************************************
447dc86dfdSMatthias Ringwald ---------------------------END-OF-HEADER------------------------------
457dc86dfdSMatthias Ringwald File    : SEGGER_RTT_printf.c
467dc86dfdSMatthias Ringwald Purpose : Replacement for printf to write formatted data via RTT
47*ce6f85e7SMatthias Ringwald Revision: $Rev: 17697 $
487dc86dfdSMatthias Ringwald ----------------------------------------------------------------------
497dc86dfdSMatthias Ringwald */
507dc86dfdSMatthias Ringwald #include "SEGGER_RTT.h"
517dc86dfdSMatthias Ringwald #include "SEGGER_RTT_Conf.h"
527dc86dfdSMatthias Ringwald 
537dc86dfdSMatthias Ringwald /*********************************************************************
547dc86dfdSMatthias Ringwald *
557dc86dfdSMatthias Ringwald *       Defines, configurable
567dc86dfdSMatthias Ringwald *
577dc86dfdSMatthias Ringwald **********************************************************************
587dc86dfdSMatthias Ringwald */
597dc86dfdSMatthias Ringwald 
607dc86dfdSMatthias Ringwald #ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE
617dc86dfdSMatthias Ringwald   #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64)
627dc86dfdSMatthias Ringwald #endif
637dc86dfdSMatthias Ringwald 
647dc86dfdSMatthias Ringwald #include <stdlib.h>
657dc86dfdSMatthias Ringwald #include <stdarg.h>
667dc86dfdSMatthias Ringwald 
677dc86dfdSMatthias Ringwald 
687dc86dfdSMatthias Ringwald #define FORMAT_FLAG_LEFT_JUSTIFY   (1u << 0)
697dc86dfdSMatthias Ringwald #define FORMAT_FLAG_PAD_ZERO       (1u << 1)
707dc86dfdSMatthias Ringwald #define FORMAT_FLAG_PRINT_SIGN     (1u << 2)
717dc86dfdSMatthias Ringwald #define FORMAT_FLAG_ALTERNATE      (1u << 3)
727dc86dfdSMatthias Ringwald 
737dc86dfdSMatthias Ringwald /*********************************************************************
747dc86dfdSMatthias Ringwald *
757dc86dfdSMatthias Ringwald *       Types
767dc86dfdSMatthias Ringwald *
777dc86dfdSMatthias Ringwald **********************************************************************
787dc86dfdSMatthias Ringwald */
797dc86dfdSMatthias Ringwald 
807dc86dfdSMatthias Ringwald typedef struct {
817dc86dfdSMatthias Ringwald   char*     pBuffer;
827dc86dfdSMatthias Ringwald   unsigned  BufferSize;
837dc86dfdSMatthias Ringwald   unsigned  Cnt;
847dc86dfdSMatthias Ringwald 
857dc86dfdSMatthias Ringwald   int   ReturnValue;
867dc86dfdSMatthias Ringwald 
877dc86dfdSMatthias Ringwald   unsigned RTTBufferIndex;
887dc86dfdSMatthias Ringwald } SEGGER_RTT_PRINTF_DESC;
897dc86dfdSMatthias Ringwald 
907dc86dfdSMatthias Ringwald /*********************************************************************
917dc86dfdSMatthias Ringwald *
927dc86dfdSMatthias Ringwald *       Function prototypes
937dc86dfdSMatthias Ringwald *
947dc86dfdSMatthias Ringwald **********************************************************************
957dc86dfdSMatthias Ringwald */
967dc86dfdSMatthias Ringwald 
977dc86dfdSMatthias Ringwald /*********************************************************************
987dc86dfdSMatthias Ringwald *
997dc86dfdSMatthias Ringwald *       Static code
1007dc86dfdSMatthias Ringwald *
1017dc86dfdSMatthias Ringwald **********************************************************************
1027dc86dfdSMatthias Ringwald */
1037dc86dfdSMatthias Ringwald /*********************************************************************
1047dc86dfdSMatthias Ringwald *
1057dc86dfdSMatthias Ringwald *       _StoreChar
1067dc86dfdSMatthias Ringwald */
_StoreChar(SEGGER_RTT_PRINTF_DESC * p,char c)1077dc86dfdSMatthias Ringwald static void _StoreChar(SEGGER_RTT_PRINTF_DESC * p, char c) {
1087dc86dfdSMatthias Ringwald   unsigned Cnt;
1097dc86dfdSMatthias Ringwald 
1107dc86dfdSMatthias Ringwald   Cnt = p->Cnt;
1117dc86dfdSMatthias Ringwald   if ((Cnt + 1u) <= p->BufferSize) {
1127dc86dfdSMatthias Ringwald     *(p->pBuffer + Cnt) = c;
1137dc86dfdSMatthias Ringwald     p->Cnt = Cnt + 1u;
1147dc86dfdSMatthias Ringwald     p->ReturnValue++;
1157dc86dfdSMatthias Ringwald   }
1167dc86dfdSMatthias Ringwald   //
1177dc86dfdSMatthias Ringwald   // Write part of string, when the buffer is full
1187dc86dfdSMatthias Ringwald   //
1197dc86dfdSMatthias Ringwald   if (p->Cnt == p->BufferSize) {
1207dc86dfdSMatthias Ringwald     if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) {
1217dc86dfdSMatthias Ringwald       p->ReturnValue = -1;
1227dc86dfdSMatthias Ringwald     } else {
1237dc86dfdSMatthias Ringwald       p->Cnt = 0u;
1247dc86dfdSMatthias Ringwald     }
1257dc86dfdSMatthias Ringwald   }
1267dc86dfdSMatthias Ringwald }
1277dc86dfdSMatthias Ringwald 
1287dc86dfdSMatthias Ringwald /*********************************************************************
1297dc86dfdSMatthias Ringwald *
1307dc86dfdSMatthias Ringwald *       _PrintUnsigned
1317dc86dfdSMatthias Ringwald */
_PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc,unsigned v,unsigned Base,unsigned NumDigits,unsigned FieldWidth,unsigned FormatFlags)1327dc86dfdSMatthias Ringwald static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) {
1337dc86dfdSMatthias Ringwald   static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
1347dc86dfdSMatthias Ringwald   unsigned Div;
1357dc86dfdSMatthias Ringwald   unsigned Digit;
1367dc86dfdSMatthias Ringwald   unsigned Number;
1377dc86dfdSMatthias Ringwald   unsigned Width;
1387dc86dfdSMatthias Ringwald   char c;
1397dc86dfdSMatthias Ringwald 
1407dc86dfdSMatthias Ringwald   Number = v;
1417dc86dfdSMatthias Ringwald   Digit = 1u;
1427dc86dfdSMatthias Ringwald   //
1437dc86dfdSMatthias Ringwald   // Get actual field width
1447dc86dfdSMatthias Ringwald   //
1457dc86dfdSMatthias Ringwald   Width = 1u;
1467dc86dfdSMatthias Ringwald   while (Number >= Base) {
1477dc86dfdSMatthias Ringwald     Number = (Number / Base);
1487dc86dfdSMatthias Ringwald     Width++;
1497dc86dfdSMatthias Ringwald   }
1507dc86dfdSMatthias Ringwald   if (NumDigits > Width) {
1517dc86dfdSMatthias Ringwald     Width = NumDigits;
1527dc86dfdSMatthias Ringwald   }
1537dc86dfdSMatthias Ringwald   //
1547dc86dfdSMatthias Ringwald   // Print leading chars if necessary
1557dc86dfdSMatthias Ringwald   //
1567dc86dfdSMatthias Ringwald   if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) {
1577dc86dfdSMatthias Ringwald     if (FieldWidth != 0u) {
1587dc86dfdSMatthias Ringwald       if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) {
1597dc86dfdSMatthias Ringwald         c = '0';
1607dc86dfdSMatthias Ringwald       } else {
1617dc86dfdSMatthias Ringwald         c = ' ';
1627dc86dfdSMatthias Ringwald       }
1637dc86dfdSMatthias Ringwald       while ((FieldWidth != 0u) && (Width < FieldWidth)) {
1647dc86dfdSMatthias Ringwald         FieldWidth--;
1657dc86dfdSMatthias Ringwald         _StoreChar(pBufferDesc, c);
1667dc86dfdSMatthias Ringwald         if (pBufferDesc->ReturnValue < 0) {
1677dc86dfdSMatthias Ringwald           break;
1687dc86dfdSMatthias Ringwald         }
1697dc86dfdSMatthias Ringwald       }
1707dc86dfdSMatthias Ringwald     }
1717dc86dfdSMatthias Ringwald   }
1727dc86dfdSMatthias Ringwald   if (pBufferDesc->ReturnValue >= 0) {
1737dc86dfdSMatthias Ringwald     //
1747dc86dfdSMatthias Ringwald     // Compute Digit.
1757dc86dfdSMatthias Ringwald     // Loop until Digit has the value of the highest digit required.
1767dc86dfdSMatthias Ringwald     // Example: If the output is 345 (Base 10), loop 2 times until Digit is 100.
1777dc86dfdSMatthias Ringwald     //
1787dc86dfdSMatthias Ringwald     while (1) {
1797dc86dfdSMatthias Ringwald       if (NumDigits > 1u) {       // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned)
1807dc86dfdSMatthias Ringwald         NumDigits--;
1817dc86dfdSMatthias Ringwald       } else {
1827dc86dfdSMatthias Ringwald         Div = v / Digit;
1837dc86dfdSMatthias Ringwald         if (Div < Base) {        // Is our divider big enough to extract the highest digit from value? => Done
1847dc86dfdSMatthias Ringwald           break;
1857dc86dfdSMatthias Ringwald         }
1867dc86dfdSMatthias Ringwald       }
1877dc86dfdSMatthias Ringwald       Digit *= Base;
1887dc86dfdSMatthias Ringwald     }
1897dc86dfdSMatthias Ringwald     //
1907dc86dfdSMatthias Ringwald     // Output digits
1917dc86dfdSMatthias Ringwald     //
1927dc86dfdSMatthias Ringwald     do {
1937dc86dfdSMatthias Ringwald       Div = v / Digit;
1947dc86dfdSMatthias Ringwald       v -= Div * Digit;
1957dc86dfdSMatthias Ringwald       _StoreChar(pBufferDesc, _aV2C[Div]);
1967dc86dfdSMatthias Ringwald       if (pBufferDesc->ReturnValue < 0) {
1977dc86dfdSMatthias Ringwald         break;
1987dc86dfdSMatthias Ringwald       }
1997dc86dfdSMatthias Ringwald       Digit /= Base;
2007dc86dfdSMatthias Ringwald     } while (Digit);
2017dc86dfdSMatthias Ringwald     //
2027dc86dfdSMatthias Ringwald     // Print trailing spaces if necessary
2037dc86dfdSMatthias Ringwald     //
2047dc86dfdSMatthias Ringwald     if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) {
2057dc86dfdSMatthias Ringwald       if (FieldWidth != 0u) {
2067dc86dfdSMatthias Ringwald         while ((FieldWidth != 0u) && (Width < FieldWidth)) {
2077dc86dfdSMatthias Ringwald           FieldWidth--;
2087dc86dfdSMatthias Ringwald           _StoreChar(pBufferDesc, ' ');
2097dc86dfdSMatthias Ringwald           if (pBufferDesc->ReturnValue < 0) {
2107dc86dfdSMatthias Ringwald             break;
2117dc86dfdSMatthias Ringwald           }
2127dc86dfdSMatthias Ringwald         }
2137dc86dfdSMatthias Ringwald       }
2147dc86dfdSMatthias Ringwald     }
2157dc86dfdSMatthias Ringwald   }
2167dc86dfdSMatthias Ringwald }
2177dc86dfdSMatthias Ringwald 
2187dc86dfdSMatthias Ringwald /*********************************************************************
2197dc86dfdSMatthias Ringwald *
2207dc86dfdSMatthias Ringwald *       _PrintInt
2217dc86dfdSMatthias Ringwald */
_PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc,int v,unsigned Base,unsigned NumDigits,unsigned FieldWidth,unsigned FormatFlags)2227dc86dfdSMatthias Ringwald static void _PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) {
2237dc86dfdSMatthias Ringwald   unsigned Width;
2247dc86dfdSMatthias Ringwald   int Number;
2257dc86dfdSMatthias Ringwald 
2267dc86dfdSMatthias Ringwald   Number = (v < 0) ? -v : v;
2277dc86dfdSMatthias Ringwald 
2287dc86dfdSMatthias Ringwald   //
2297dc86dfdSMatthias Ringwald   // Get actual field width
2307dc86dfdSMatthias Ringwald   //
2317dc86dfdSMatthias Ringwald   Width = 1u;
2327dc86dfdSMatthias Ringwald   while (Number >= (int)Base) {
2337dc86dfdSMatthias Ringwald     Number = (Number / (int)Base);
2347dc86dfdSMatthias Ringwald     Width++;
2357dc86dfdSMatthias Ringwald   }
2367dc86dfdSMatthias Ringwald   if (NumDigits > Width) {
2377dc86dfdSMatthias Ringwald     Width = NumDigits;
2387dc86dfdSMatthias Ringwald   }
2397dc86dfdSMatthias Ringwald   if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) {
2407dc86dfdSMatthias Ringwald     FieldWidth--;
2417dc86dfdSMatthias Ringwald   }
2427dc86dfdSMatthias Ringwald 
2437dc86dfdSMatthias Ringwald   //
2447dc86dfdSMatthias Ringwald   // Print leading spaces if necessary
2457dc86dfdSMatthias Ringwald   //
2467dc86dfdSMatthias Ringwald   if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) {
2477dc86dfdSMatthias Ringwald     if (FieldWidth != 0u) {
2487dc86dfdSMatthias Ringwald       while ((FieldWidth != 0u) && (Width < FieldWidth)) {
2497dc86dfdSMatthias Ringwald         FieldWidth--;
2507dc86dfdSMatthias Ringwald         _StoreChar(pBufferDesc, ' ');
2517dc86dfdSMatthias Ringwald         if (pBufferDesc->ReturnValue < 0) {
2527dc86dfdSMatthias Ringwald           break;
2537dc86dfdSMatthias Ringwald         }
2547dc86dfdSMatthias Ringwald       }
2557dc86dfdSMatthias Ringwald     }
2567dc86dfdSMatthias Ringwald   }
2577dc86dfdSMatthias Ringwald   //
2587dc86dfdSMatthias Ringwald   // Print sign if necessary
2597dc86dfdSMatthias Ringwald   //
2607dc86dfdSMatthias Ringwald   if (pBufferDesc->ReturnValue >= 0) {
2617dc86dfdSMatthias Ringwald     if (v < 0) {
2627dc86dfdSMatthias Ringwald       v = -v;
2637dc86dfdSMatthias Ringwald       _StoreChar(pBufferDesc, '-');
2647dc86dfdSMatthias Ringwald     } else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) {
2657dc86dfdSMatthias Ringwald       _StoreChar(pBufferDesc, '+');
2667dc86dfdSMatthias Ringwald     } else {
2677dc86dfdSMatthias Ringwald 
2687dc86dfdSMatthias Ringwald     }
2697dc86dfdSMatthias Ringwald     if (pBufferDesc->ReturnValue >= 0) {
2707dc86dfdSMatthias Ringwald       //
2717dc86dfdSMatthias Ringwald       // Print leading zeros if necessary
2727dc86dfdSMatthias Ringwald       //
2737dc86dfdSMatthias Ringwald       if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) {
2747dc86dfdSMatthias Ringwald         if (FieldWidth != 0u) {
2757dc86dfdSMatthias Ringwald           while ((FieldWidth != 0u) && (Width < FieldWidth)) {
2767dc86dfdSMatthias Ringwald             FieldWidth--;
2777dc86dfdSMatthias Ringwald             _StoreChar(pBufferDesc, '0');
2787dc86dfdSMatthias Ringwald             if (pBufferDesc->ReturnValue < 0) {
2797dc86dfdSMatthias Ringwald               break;
2807dc86dfdSMatthias Ringwald             }
2817dc86dfdSMatthias Ringwald           }
2827dc86dfdSMatthias Ringwald         }
2837dc86dfdSMatthias Ringwald       }
2847dc86dfdSMatthias Ringwald       if (pBufferDesc->ReturnValue >= 0) {
2857dc86dfdSMatthias Ringwald         //
2867dc86dfdSMatthias Ringwald         // Print number without sign
2877dc86dfdSMatthias Ringwald         //
2887dc86dfdSMatthias Ringwald         _PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags);
2897dc86dfdSMatthias Ringwald       }
2907dc86dfdSMatthias Ringwald     }
2917dc86dfdSMatthias Ringwald   }
2927dc86dfdSMatthias Ringwald }
2937dc86dfdSMatthias Ringwald 
2947dc86dfdSMatthias Ringwald /*********************************************************************
2957dc86dfdSMatthias Ringwald *
2967dc86dfdSMatthias Ringwald *       Public code
2977dc86dfdSMatthias Ringwald *
2987dc86dfdSMatthias Ringwald **********************************************************************
2997dc86dfdSMatthias Ringwald */
3007dc86dfdSMatthias Ringwald /*********************************************************************
3017dc86dfdSMatthias Ringwald *
3027dc86dfdSMatthias Ringwald *       SEGGER_RTT_vprintf
3037dc86dfdSMatthias Ringwald *
3047dc86dfdSMatthias Ringwald *  Function description
3057dc86dfdSMatthias Ringwald *    Stores a formatted string in SEGGER RTT control block.
3067dc86dfdSMatthias Ringwald *    This data is read by the host.
3077dc86dfdSMatthias Ringwald *
3087dc86dfdSMatthias Ringwald *  Parameters
3097dc86dfdSMatthias Ringwald *    BufferIndex  Index of "Up"-buffer to be used. (e.g. 0 for "Terminal")
3107dc86dfdSMatthias Ringwald *    sFormat      Pointer to format string
3117dc86dfdSMatthias Ringwald *    pParamList   Pointer to the list of arguments for the format string
3127dc86dfdSMatthias Ringwald *
3137dc86dfdSMatthias Ringwald *  Return values
3147dc86dfdSMatthias Ringwald *    >= 0:  Number of bytes which have been stored in the "Up"-buffer.
3157dc86dfdSMatthias Ringwald *     < 0:  Error
3167dc86dfdSMatthias Ringwald */
SEGGER_RTT_vprintf(unsigned BufferIndex,const char * sFormat,va_list * pParamList)3177dc86dfdSMatthias Ringwald int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) {
3187dc86dfdSMatthias Ringwald   char c;
3197dc86dfdSMatthias Ringwald   SEGGER_RTT_PRINTF_DESC BufferDesc;
3207dc86dfdSMatthias Ringwald   int v;
3217dc86dfdSMatthias Ringwald   unsigned NumDigits;
3227dc86dfdSMatthias Ringwald   unsigned FormatFlags;
3237dc86dfdSMatthias Ringwald   unsigned FieldWidth;
3247dc86dfdSMatthias Ringwald   char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE];
3257dc86dfdSMatthias Ringwald 
3267dc86dfdSMatthias Ringwald   BufferDesc.pBuffer        = acBuffer;
3277dc86dfdSMatthias Ringwald   BufferDesc.BufferSize     = SEGGER_RTT_PRINTF_BUFFER_SIZE;
3287dc86dfdSMatthias Ringwald   BufferDesc.Cnt            = 0u;
3297dc86dfdSMatthias Ringwald   BufferDesc.RTTBufferIndex = BufferIndex;
3307dc86dfdSMatthias Ringwald   BufferDesc.ReturnValue    = 0;
3317dc86dfdSMatthias Ringwald 
3327dc86dfdSMatthias Ringwald   do {
3337dc86dfdSMatthias Ringwald     c = *sFormat;
3347dc86dfdSMatthias Ringwald     sFormat++;
3357dc86dfdSMatthias Ringwald     if (c == 0u) {
3367dc86dfdSMatthias Ringwald       break;
3377dc86dfdSMatthias Ringwald     }
3387dc86dfdSMatthias Ringwald     if (c == '%') {
3397dc86dfdSMatthias Ringwald       //
3407dc86dfdSMatthias Ringwald       // Filter out flags
3417dc86dfdSMatthias Ringwald       //
3427dc86dfdSMatthias Ringwald       FormatFlags = 0u;
3437dc86dfdSMatthias Ringwald       v = 1;
3447dc86dfdSMatthias Ringwald       do {
3457dc86dfdSMatthias Ringwald         c = *sFormat;
3467dc86dfdSMatthias Ringwald         switch (c) {
3477dc86dfdSMatthias Ringwald         case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break;
3487dc86dfdSMatthias Ringwald         case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO;     sFormat++; break;
3497dc86dfdSMatthias Ringwald         case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN;   sFormat++; break;
3507dc86dfdSMatthias Ringwald         case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE;    sFormat++; break;
3517dc86dfdSMatthias Ringwald         default:  v = 0; break;
3527dc86dfdSMatthias Ringwald         }
3537dc86dfdSMatthias Ringwald       } while (v);
3547dc86dfdSMatthias Ringwald       //
3557dc86dfdSMatthias Ringwald       // filter out field with
3567dc86dfdSMatthias Ringwald       //
3577dc86dfdSMatthias Ringwald       FieldWidth = 0u;
3587dc86dfdSMatthias Ringwald       do {
3597dc86dfdSMatthias Ringwald         c = *sFormat;
3607dc86dfdSMatthias Ringwald         if ((c < '0') || (c > '9')) {
3617dc86dfdSMatthias Ringwald           break;
3627dc86dfdSMatthias Ringwald         }
3637dc86dfdSMatthias Ringwald         sFormat++;
3647dc86dfdSMatthias Ringwald         FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0');
3657dc86dfdSMatthias Ringwald       } while (1);
3667dc86dfdSMatthias Ringwald 
3677dc86dfdSMatthias Ringwald       //
3687dc86dfdSMatthias Ringwald       // Filter out precision (number of digits to display)
3697dc86dfdSMatthias Ringwald       //
3707dc86dfdSMatthias Ringwald       NumDigits = 0u;
3717dc86dfdSMatthias Ringwald       c = *sFormat;
3727dc86dfdSMatthias Ringwald       if (c == '.') {
3737dc86dfdSMatthias Ringwald         sFormat++;
3747dc86dfdSMatthias Ringwald         do {
3757dc86dfdSMatthias Ringwald           c = *sFormat;
3767dc86dfdSMatthias Ringwald           if ((c < '0') || (c > '9')) {
3777dc86dfdSMatthias Ringwald             break;
3787dc86dfdSMatthias Ringwald           }
3797dc86dfdSMatthias Ringwald           sFormat++;
3807dc86dfdSMatthias Ringwald           NumDigits = NumDigits * 10u + ((unsigned)c - '0');
3817dc86dfdSMatthias Ringwald         } while (1);
3827dc86dfdSMatthias Ringwald       }
3837dc86dfdSMatthias Ringwald       //
3847dc86dfdSMatthias Ringwald       // Filter out length modifier
3857dc86dfdSMatthias Ringwald       //
3867dc86dfdSMatthias Ringwald       c = *sFormat;
3877dc86dfdSMatthias Ringwald       do {
3887dc86dfdSMatthias Ringwald         if ((c == 'l') || (c == 'h')) {
3897dc86dfdSMatthias Ringwald           sFormat++;
3907dc86dfdSMatthias Ringwald           c = *sFormat;
3917dc86dfdSMatthias Ringwald         } else {
3927dc86dfdSMatthias Ringwald           break;
3937dc86dfdSMatthias Ringwald         }
3947dc86dfdSMatthias Ringwald       } while (1);
3957dc86dfdSMatthias Ringwald       //
3967dc86dfdSMatthias Ringwald       // Handle specifiers
3977dc86dfdSMatthias Ringwald       //
3987dc86dfdSMatthias Ringwald       switch (c) {
3997dc86dfdSMatthias Ringwald       case 'c': {
4007dc86dfdSMatthias Ringwald         char c0;
4017dc86dfdSMatthias Ringwald         v = va_arg(*pParamList, int);
4027dc86dfdSMatthias Ringwald         c0 = (char)v;
4037dc86dfdSMatthias Ringwald         _StoreChar(&BufferDesc, c0);
4047dc86dfdSMatthias Ringwald         break;
4057dc86dfdSMatthias Ringwald       }
4067dc86dfdSMatthias Ringwald       case 'd':
4077dc86dfdSMatthias Ringwald         v = va_arg(*pParamList, int);
4087dc86dfdSMatthias Ringwald         _PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags);
4097dc86dfdSMatthias Ringwald         break;
4107dc86dfdSMatthias Ringwald       case 'u':
4117dc86dfdSMatthias Ringwald         v = va_arg(*pParamList, int);
4127dc86dfdSMatthias Ringwald         _PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags);
4137dc86dfdSMatthias Ringwald         break;
4147dc86dfdSMatthias Ringwald       case 'x':
4157dc86dfdSMatthias Ringwald       case 'X':
4167dc86dfdSMatthias Ringwald         v = va_arg(*pParamList, int);
4177dc86dfdSMatthias Ringwald         _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags);
4187dc86dfdSMatthias Ringwald         break;
4197dc86dfdSMatthias Ringwald       case 's':
4207dc86dfdSMatthias Ringwald         {
4217dc86dfdSMatthias Ringwald           const char * s = va_arg(*pParamList, const char *);
4227dc86dfdSMatthias Ringwald           do {
4237dc86dfdSMatthias Ringwald             c = *s;
4247dc86dfdSMatthias Ringwald             s++;
4257dc86dfdSMatthias Ringwald             if (c == '\0') {
4267dc86dfdSMatthias Ringwald               break;
4277dc86dfdSMatthias Ringwald             }
4287dc86dfdSMatthias Ringwald            _StoreChar(&BufferDesc, c);
4297dc86dfdSMatthias Ringwald           } while (BufferDesc.ReturnValue >= 0);
4307dc86dfdSMatthias Ringwald         }
4317dc86dfdSMatthias Ringwald         break;
4327dc86dfdSMatthias Ringwald       case 'p':
4337dc86dfdSMatthias Ringwald         v = va_arg(*pParamList, int);
4347dc86dfdSMatthias Ringwald         _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u);
4357dc86dfdSMatthias Ringwald         break;
4367dc86dfdSMatthias Ringwald       case '%':
4377dc86dfdSMatthias Ringwald         _StoreChar(&BufferDesc, '%');
4387dc86dfdSMatthias Ringwald         break;
4397dc86dfdSMatthias Ringwald       default:
4407dc86dfdSMatthias Ringwald         break;
4417dc86dfdSMatthias Ringwald       }
4427dc86dfdSMatthias Ringwald       sFormat++;
4437dc86dfdSMatthias Ringwald     } else {
4447dc86dfdSMatthias Ringwald       _StoreChar(&BufferDesc, c);
4457dc86dfdSMatthias Ringwald     }
4467dc86dfdSMatthias Ringwald   } while (BufferDesc.ReturnValue >= 0);
4477dc86dfdSMatthias Ringwald 
4487dc86dfdSMatthias Ringwald   if (BufferDesc.ReturnValue > 0) {
4497dc86dfdSMatthias Ringwald     //
4507dc86dfdSMatthias Ringwald     // Write remaining data, if any
4517dc86dfdSMatthias Ringwald     //
4527dc86dfdSMatthias Ringwald     if (BufferDesc.Cnt != 0u) {
4537dc86dfdSMatthias Ringwald       SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt);
4547dc86dfdSMatthias Ringwald     }
4557dc86dfdSMatthias Ringwald     BufferDesc.ReturnValue += (int)BufferDesc.Cnt;
4567dc86dfdSMatthias Ringwald   }
4577dc86dfdSMatthias Ringwald   return BufferDesc.ReturnValue;
4587dc86dfdSMatthias Ringwald }
4597dc86dfdSMatthias Ringwald 
4607dc86dfdSMatthias Ringwald /*********************************************************************
4617dc86dfdSMatthias Ringwald *
4627dc86dfdSMatthias Ringwald *       SEGGER_RTT_printf
4637dc86dfdSMatthias Ringwald *
4647dc86dfdSMatthias Ringwald *  Function description
4657dc86dfdSMatthias Ringwald *    Stores a formatted string in SEGGER RTT control block.
4667dc86dfdSMatthias Ringwald *    This data is read by the host.
4677dc86dfdSMatthias Ringwald *
4687dc86dfdSMatthias Ringwald *  Parameters
4697dc86dfdSMatthias Ringwald *    BufferIndex  Index of "Up"-buffer to be used. (e.g. 0 for "Terminal")
4707dc86dfdSMatthias Ringwald *    sFormat      Pointer to format string, followed by the arguments for conversion
4717dc86dfdSMatthias Ringwald *
4727dc86dfdSMatthias Ringwald *  Return values
4737dc86dfdSMatthias Ringwald *    >= 0:  Number of bytes which have been stored in the "Up"-buffer.
4747dc86dfdSMatthias Ringwald *     < 0:  Error
4757dc86dfdSMatthias Ringwald *
4767dc86dfdSMatthias Ringwald *  Notes
4777dc86dfdSMatthias Ringwald *    (1) Conversion specifications have following syntax:
4787dc86dfdSMatthias Ringwald *          %[flags][FieldWidth][.Precision]ConversionSpecifier
4797dc86dfdSMatthias Ringwald *    (2) Supported flags:
4807dc86dfdSMatthias Ringwald *          -: Left justify within the field width
4817dc86dfdSMatthias Ringwald *          +: Always print sign extension for signed conversions
4827dc86dfdSMatthias Ringwald *          0: Pad with 0 instead of spaces. Ignored when using '-'-flag or precision
4837dc86dfdSMatthias Ringwald *        Supported conversion specifiers:
4847dc86dfdSMatthias Ringwald *          c: Print the argument as one char
4857dc86dfdSMatthias Ringwald *          d: Print the argument as a signed integer
4867dc86dfdSMatthias Ringwald *          u: Print the argument as an unsigned integer
4877dc86dfdSMatthias Ringwald *          x: Print the argument as an hexadecimal integer
4887dc86dfdSMatthias Ringwald *          s: Print the string pointed to by the argument
4897dc86dfdSMatthias Ringwald *          p: Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.)
4907dc86dfdSMatthias Ringwald */
SEGGER_RTT_printf(unsigned BufferIndex,const char * sFormat,...)4917dc86dfdSMatthias Ringwald int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...) {
4927dc86dfdSMatthias Ringwald   int r;
4937dc86dfdSMatthias Ringwald   va_list ParamList;
4947dc86dfdSMatthias Ringwald 
4957dc86dfdSMatthias Ringwald   va_start(ParamList, sFormat);
4967dc86dfdSMatthias Ringwald   r = SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList);
4977dc86dfdSMatthias Ringwald   va_end(ParamList);
4987dc86dfdSMatthias Ringwald   return r;
4997dc86dfdSMatthias Ringwald }
5007dc86dfdSMatthias Ringwald /*************************** End of file ****************************/
501