text: /*
   * Copyright 2017, 2020 NXP
   * All rights reserved.
   *
   *
   * SPDX-License-Identifier: BSD-3-Clause
   *
   */
  #include <math.h>
  #include <stdarg.h>
  #include <stdlib.h>
  #include "fsl_str.h"
  #include "fsl_debug_console_conf.h"
  
  /*******************************************************************************
   * Definitions
   ******************************************************************************/
  
  /*! @brief The overflow value.*/
  #ifndef HUGE_VAL
  #define HUGE_VAL (99.e99)
  #endif /* HUGE_VAL */
  
  #ifndef MAX_FIELD_WIDTH
  #define MAX_FIELD_WIDTH 99U
  #endif
  
  #if PRINTF_ADVANCED_ENABLE
  /*! @brief Specification modifier flags for printf. */
  enum _debugconsole_printf_flag
  {
      kPRINTF_Minus             = 0x01U,  /*!< Minus FLag. */
      kPRINTF_Plus              = 0x02U,  /*!< Plus Flag. */
      kPRINTF_Space             = 0x04U,  /*!< Space Flag. */
      kPRINTF_Zero              = 0x08U,  /*!< Zero Flag. */
      kPRINTF_Pound             = 0x10U,  /*!< Pound Flag. */
      kPRINTF_LengthChar        = 0x20U,  /*!< Length: Char Flag. */
      kPRINTF_LengthShortInt    = 0x40U,  /*!< Length: Short Int Flag. */
      kPRINTF_LengthLongInt     = 0x80U,  /*!< Length: Long Int Flag. */
      kPRINTF_LengthLongLongInt = 0x100U, /*!< Length: Long Long Int Flag. */
  };
  #endif /* PRINTF_ADVANCED_ENABLE */
  
  /*! @brief Specification modifier flags for scanf. */
  enum _debugconsole_scanf_flag
  {
      kSCANF_Suppress   = 0x2U,    /*!< Suppress Flag. */
      kSCANF_DestMask   = 0x7cU,   /*!< Destination Mask. */
      kSCANF_DestChar   = 0x4U,    /*!< Destination Char Flag. */
      kSCANF_DestString = 0x8U,    /*!< Destination String FLag. */
      kSCANF_DestSet    = 0x10U,   /*!< Destination Set Flag. */
      kSCANF_DestInt    = 0x20U,   /*!< Destination Int Flag. */
      kSCANF_DestFloat  = 0x30U,   /*!< Destination Float Flag. */
      kSCANF_LengthMask = 0x1f00U, /*!< Length Mask Flag. */
  #if SCANF_ADVANCED_ENABLE
      kSCANF_LengthChar        = 0x100U, /*!< Length Char Flag. */
      kSCANF_LengthShortInt    = 0x200U, /*!< Length ShortInt Flag. */
      kSCANF_LengthLongInt     = 0x400U, /*!< Length LongInt Flag. */
      kSCANF_LengthLongLongInt = 0x800U, /*!< Length LongLongInt Flag. */
  #endif                                 /* SCANF_ADVANCED_ENABLE */
  #if SCANF_FLOAT_ENABLE
      kSCANF_LengthLongLongDouble = 0x1000U, /*!< Length LongLongDuoble Flag. */
  #endif                                     /*PRINTF_FLOAT_ENABLE */
      kSCANF_TypeSinged = 0x2000U,           /*!< TypeSinged Flag. */
  };
  
  /*! @brief Keil: suppress ellipsis warning in va_arg usage below. */
  #if defined(__CC_ARM)
  #pragma diag_suppress 1256
  #endif /* __CC_ARM */
  
  /*******************************************************************************
   * Prototypes
   ******************************************************************************/
  /*!
   * @brief Scanline function which ignores white spaces.
   *
   * @param[in]   s The address of the string pointer to update.
   * @return      String without white spaces.
   */
  static uint32_t ScanIgnoreWhiteSpace(const char **s);
  
  /*!
   * @brief Converts a radix number to a string and return its length.
   *
   * @param[in] numstr    Converted string of the number.
   * @param[in] nump      Pointer to the number.
   * @param[in] neg       Polarity of the number.
   * @param[in] radix     The radix to be converted to.
   * @param[in] use_caps  Used to identify %x/X output format.
  
   * @return Length of the converted string.
   */
  static int32_t ConvertRadixNumToString(char *numstr, void *nump, int32_t neg, int32_t radix, bool use_caps);
  
  #if PRINTF_FLOAT_ENABLE
  /*!
   * @brief Converts a floating radix number to a string and return its length.
   *
   * @param[in] numstr            Converted string of the number.
   * @param[in] nump              Pointer to the number.
   * @param[in] radix             The radix to be converted to.
   * @param[in] precision_width   Specify the precision width.
  
   * @return Length of the converted string.
   */
  static int32_t ConvertFloatRadixNumToString(char *numstr, void *nump, int32_t radix, uint32_t precision_width);
  
  /*!
   *
   */
  double modf(double input_dbl, double *intpart_ptr);
  #endif /* PRINTF_FLOAT_ENABLE */
  
  /*************Code for process formatted data*******************************/
  #if PRINTF_ADVANCED_ENABLE
  static uint8_t PrintGetSignChar(int32_t ival, uint32_t flags_used, char *schar)
  {
      uint8_t len = 1U;
      if (ival < 0)
      {
          *schar = '-';
      }
      else
      {
          if (0U != (flags_used & (uint32_t)kPRINTF_Plus))
          {
              *schar = '+';
          }
          else if (0U != (flags_used & (uint32_t)kPRINTF_Space))
          {
              *schar = ' ';
          }
          else
          {
              *schar = 0;
              len    = 0U;
          }
      }
      return len;
  }
  #endif
  
  static uint32_t PrintGetWidth(const char **p, va_list *ap)
  {
      uint32_t field_width = 0;
      uint8_t done         = 0U;
      char c;
  
      while (0U == done)
      {
          c = *(++(*p));
          if ((c >= '0') && (c <= '9'))
          {
              (field_width) = ((field_width)*10U) + ((uint32_t)c - (uint32_t)'0');
          }
  #if PRINTF_ADVANCED_ENABLE
          else if (c == '*')
          {
              (field_width) = (uint32_t)va_arg(*ap, uint32_t);
          }
  #endif /* PRINTF_ADVANCED_ENABLE */
          else
          {
              /* We've gone one char too far. */
              --(*p);
              done = 1U;
          }
      }
      return field_width;
  }
  
  static uint32_t PrintGetPrecision(const char **s, va_list *ap, bool *valid_precision_width)
  {
      const char *p            = *s;
      uint32_t precision_width = 6U;
      uint8_t done             = 0U;
  
  #if PRINTF_ADVANCED_ENABLE
      if (NULL != valid_precision_width)
      {
          *valid_precision_width = false;
      }
  #endif /* PRINTF_ADVANCED_ENABLE */
      if (*++p == '.')
      {
          /* Must get precision field width, if present. */
          precision_width = 0U;
          done            = 0U;
          while (0U == done)
          {
              char c = *++p;
              if ((c >= '0') && (c <= '9'))
              {
                  precision_width = (precision_width * 10U) + ((uint32_t)c - (uint32_t)'0');
  #if PRINTF_ADVANCED_ENABLE
                  if (NULL != valid_precision_width)
                  {
                      *valid_precision_width = true;
                  }
  #endif /* PRINTF_ADVANCED_ENABLE */
              }
  #if PRINTF_ADVANCED_ENABLE
              else if (c == '*')
              {
                  precision_width = (uint32_t)va_arg(*ap, uint32_t);
                  if (NULL != valid_precision_width)
                  {
                      *valid_precision_width = true;
                  }
              }
  #endif /* PRINTF_ADVANCED_ENABLE */
              else
              {
                  /* We've gone one char too far. */
                  --p;
                  done = 1U;
              }
          }
      }
      else
      {
          /* We've gone one char too far. */
          --p;
      }
      *s = p;
      return precision_width;
  }
  
  static uint32_t PrintIsobpu(const char c)
  {
      uint32_t ret = 0U;
      if ((c == 'o') || (c == 'b') || (c == 'p') || (c == 'u'))
      {
          ret = 1U;
      }
      return ret;
  }
  
  static uint32_t PrintIsdi(const char c)
  {
      uint32_t ret = 0U;
      if ((c == 'd') || (c == 'i'))
      {
          ret = 1U;
      }
      return ret;
  }
  
  static void PrintOutputdifFobpu(uint32_t flags_used,
                                  uint32_t field_width,
                                  uint32_t vlen,
                                  char schar,
                                  char *vstrp,
                                  printfCb cb,
                                  char *buf,
                                  int32_t *count)
  {
  #if PRINTF_ADVANCED_ENABLE
      /* Do the ZERO pad. */
      if (0U != (flags_used & (uint32_t)kPRINTF_Zero))
      {
          if ('\0' != schar)
          {
              cb(buf, count, schar, 1);
              schar = '\0';
          }
          cb(buf, count, '0', (int)field_width - (int)vlen);
          vlen = field_width;
      }
      else
      {
          if (0U == (flags_used & (uint32_t)kPRINTF_Minus))
          {
              cb(buf, count, ' ', (int)field_width - (int)vlen);
              if ('\0' != schar)
              {
                  cb(buf, count, schar, 1);
                  schar = '\0';
              }
          }
      }
      /* The string was built in reverse order, now display in correct order. */
      if ('\0' != schar)
      {
          cb(buf, count, schar, 1);
      }
  #else
      cb(buf, count, ' ', (int)field_width - (int)vlen);
  #endif /* PRINTF_ADVANCED_ENABLE */
      while ('\0' != (*vstrp))
      {
          cb(buf, count, *vstrp--, 1);
      }
  #if PRINTF_ADVANCED_ENABLE
      if (0U != (flags_used & (uint32_t)kPRINTF_Minus))
      {
          cb(buf, count, ' ', (int)field_width - (int)vlen);
      }
  #endif /* PRINTF_ADVANCED_ENABLE */
  }
  
  static void PrintOutputxX(uint32_t flags_used,
                            uint32_t field_width,
                            uint32_t vlen,
                            bool use_caps,
                            char *vstrp,
                            printfCb cb,
                            char *buf,
                            int32_t *count)
  {
  #if PRINTF_ADVANCED_ENABLE
      uint8_t dschar = 0;
      if (0U != (flags_used & (uint32_t)kPRINTF_Zero))
      {
          if (0U != (flags_used & (uint32_t)kPRINTF_Pound))
          {
              cb(buf, count, '0', 1);
              cb(buf, count, (use_caps ? 'X' : 'x'), 1);
              dschar = 1U;
          }
          cb(buf, count, '0', (int)field_width - (int)vlen);
          vlen = field_width;
      }
      else
      {
          if (0U == (flags_used & (uint32_t)kPRINTF_Minus))
          {
              if (0U != (flags_used & (uint32_t)kPRINTF_Pound))
              {
                  vlen += 2U;
              }
              cb(buf, count, ' ', (int)field_width - (int)vlen);
              if (0U != (flags_used & (uint32_t)kPRINTF_Pound))
              {
                  cb(buf, count, '0', 1);
                  cb(buf, count, (use_caps ? 'X' : 'x'), 1);
                  dschar = 1U;
              }
          }
      }
  
      if ((0U != (flags_used & (uint32_t)kPRINTF_Pound)) && (0U == dschar))
      {
          cb(buf, count, '0', 1);
          cb(buf, count, (use_caps ? 'X' : 'x'), 1);
          vlen += 2U;
      }
  #else
      cb(buf, count, ' ', (int)field_width - (int)vlen);
  #endif /* PRINTF_ADVANCED_ENABLE */
      while ('\0' != (*vstrp))
      {
          cb(buf, count, *vstrp--, 1);
      }
  #if PRINTF_ADVANCED_ENABLE
      if (0U != (flags_used & (uint32_t)kPRINTF_Minus))
      {
          cb(buf, count, ' ', (int)field_width - (int)vlen);
      }
  #endif /* PRINTF_ADVANCED_ENABLE */
  }
  
  static uint32_t PrintIsfF(const char c)
  {
      uint32_t ret = 0U;
      if ((c == 'f') || (c == 'F'))
      {
          ret = 1U;
      }
      return ret;
  }
  
  static uint32_t PrintIsxX(const char c)
  {
      uint32_t ret = 0U;
      if ((c == 'x') || (c == 'X'))
      {
          ret = 1U;
      }
      return ret;
  }
  
  #if PRINTF_ADVANCED_ENABLE
  static uint32_t PrintCheckFlags(const char **s)
  {
      const char *p = *s;
      /* First check for specification modifier flags. */
      uint32_t flags_used = 0U;
      bool done           = false;
      while (false == done)
      {
          switch (*++p)
          {
              case '-':
                  flags_used |= (uint32_t)kPRINTF_Minus;
                  break;
              case '+':
                  flags_used |= (uint32_t)kPRINTF_Plus;
                  break;
              case ' ':
                  flags_used |= (uint32_t)kPRINTF_Space;
                  break;
              case '0':
                  flags_used |= (uint32_t)kPRINTF_Zero;
                  break;
              case '#':
                  flags_used |= (uint32_t)kPRINTF_Pound;
                  break;
              default:
                  /* We've gone one char too far. */
                  --p;
                  done = true;
                  break;
          }
      }
      *s = p;
      return flags_used;
  }
  #endif /* PRINTF_ADVANCED_ENABLE */
  
  #if PRINTF_ADVANCED_ENABLE
  /*
   * Check for the length modifier.
   */
  static uint32_t PrintGetLengthFlag(const char **s)
  {
      const char *p = *s;
      /* First check for specification modifier flags. */
      uint32_t flags_used = 0U;
  
      switch (/* c = */ *++p)
      {
          case 'h':
              if (*++p != 'h')
              {
                  flags_used |= (uint32_t)kPRINTF_LengthShortInt;
                  --p;
              }
              else
              {
                  flags_used |= (uint32_t)kPRINTF_LengthChar;
              }
              break;
          case 'l':
              if (*++p != 'l')
              {
                  flags_used |= (uint32_t)kPRINTF_LengthLongInt;
                  --p;
              }
              else
              {
                  flags_used |= (uint32_t)kPRINTF_LengthLongLongInt;
              }
              break;
          default:
              /* we've gone one char too far */
              --p;
              break;
      }
      *s = p;
      return flags_used;
  }
  #endif /* PRINTF_ADVANCED_ENABLE */
  
  static uint8_t PrintGetRadixFromobpu(const char c)
  {
      uint8_t radix;
  
      if (c == 'o')
      {
          radix = 8U;
      }
      else if (c == 'b')
      {
          radix = 2U;
      }
      else if (c == 'p')
      {
          radix = 16U;
      }
      else
      {
          radix = 10U;
      }
      return radix;
  }
  
  static uint32_t ScanIsWhiteSpace(const char c)
  {
      uint32_t ret = 0U;
      if ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r') || (c == '\v') || (c == '\f'))
      {
          ret = 1U;
      }
      return ret;
  }
  
  static uint32_t ScanIgnoreWhiteSpace(const char **s)
  {
      uint32_t count = 0U;
      char c;
  
      c = **s;
      while (1U == ScanIsWhiteSpace(c))
      {
          count++;
          (*s)++;
          c = **s;
      }
      return count;
  }
  
  static int32_t ConvertRadixNumToString(char *numstr, void *nump, int32_t neg, int32_t radix, bool use_caps)
  {
  #if PRINTF_ADVANCED_ENABLE
      int64_t a;
      int64_t b;
      int64_t c;
  
      uint64_t ua;
      uint64_t ub;
      uint64_t uc;
      uint64_t uc_param;
  #else
      int32_t a;
      int32_t b;
      int32_t c;
  
      uint32_t ua;
      uint32_t ub;
      uint32_t uc;
      uint32_t uc_param;
  #endif /* PRINTF_ADVANCED_ENABLE */
  
      int32_t nlen;
      char *nstrp;
  
      nlen     = 0;
      nstrp    = numstr;
      *nstrp++ = '\0';
  
      if (0 != neg)
      {
  #if PRINTF_ADVANCED_ENABLE
          a = *(int64_t *)nump;
  #else
          a = *(int32_t *)nump;
  #endif /* PRINTF_ADVANCED_ENABLE */
          if (a == 0)
          {
              *nstrp = '0';
              ++nlen;
              return nlen;
          }
          while (a != 0)
          {
  #if PRINTF_ADVANCED_ENABLE
              b = (int64_t)a / (int64_t)radix;
              c = (int64_t)a - ((int64_t)b * (int64_t)radix);
              if (c < 0)
              {
                  uc       = (uint64_t)c;
                  uc_param = ~uc;
                  c        = (int64_t)uc_param + 1 + (int64_t)'0';
              }
  #else
              b = a / radix;
              c = a - (b * radix);
              if (c < 0)
              {
                  uc       = (uint32_t)c;
                  uc_param = ~uc;
                  c        = (int32_t)uc_param + 1 + (int32_t)'0';
              }
  #endif /* PRINTF_ADVANCED_ENABLE */
              else
              {
                  c = c + (int32_t)'0';
              }
              a        = b;
              *nstrp++ = (char)c;
              ++nlen;
          }
      }
      else
      {
  #if PRINTF_ADVANCED_ENABLE
          ua = *(uint64_t *)nump;
  #else
          ua = *(uint32_t *)nump;
  #endif /* PRINTF_ADVANCED_ENABLE */
          if (ua == 0U)
          {
              *nstrp = '0';
              ++nlen;
              return nlen;
          }
          while (ua != 0U)
          {
  #if PRINTF_ADVANCED_ENABLE
              ub = (uint64_t)ua / (uint64_t)radix;
              uc = (uint64_t)ua - ((uint64_t)ub * (uint64_t)radix);
  #else
              ub = ua / (uint32_t)radix;
              uc = ua - (ub * (uint32_t)radix);
  #endif /* PRINTF_ADVANCED_ENABLE */
  
              if (uc < 10U)
              {
                  uc = uc + (uint32_t)'0';
              }
              else
              {
                  uc = uc - 10U + (uint32_t)(use_caps ? 'A' : 'a');
              }
              ua       = ub;
              *nstrp++ = (char)uc;
              ++nlen;
          }
      }
      return nlen;
  }
  
  #if PRINTF_FLOAT_ENABLE
  static int32_t ConvertFloatRadixNumToString(char *numstr, void *nump, int32_t radix, uint32_t precision_width)
  {
      int32_t a;
      int32_t b;
      int32_t c;
      int32_t i;
      uint32_t uc;
      double fa;
      double dc;
      double fb;
      double r;
      double fractpart;
      double intpart;
  
      int32_t nlen;
      char *nstrp;
      nlen     = 0;
      nstrp    = numstr;
      *nstrp++ = '\0';
      r        = *(double *)nump;
      if (!r)
      {
          *nstrp = '0';
          ++nlen;
          return nlen;
      }
      fractpart = modf((double)r, (double *)&intpart);
      /* Process fractional part. */
      for (i = 0; i < precision_width; i++)
      {
          fractpart *= radix;
      }
      if (r >= 0)
      {
          fa = fractpart + (double)0.5;
          if (fa >= pow(10, precision_width))
          {
              intpart++;
          }
      }
      else
      {
          fa = fractpart - (double)0.5;
          if (fa <= -pow(10, precision_width))
          {
              intpart--;
          }
      }
      for (i = 0; i < precision_width; i++)
      {
          fb = fa / (int32_t)radix;
          dc = (fa - (int64_t)fb * (int32_t)radix);
          c  = (int32_t)dc;
          if (c < 0)
          {
              uc = (uint32_t)c;
              c  = (int32_t)(~uc) + 1 + '0';
          }
          else
          {
              c = c + '0';
          }
          fa       = fb;
          *nstrp++ = (char)c;
          ++nlen;
      }
      *nstrp++ = (char)'.';
      ++nlen;
      a = (int32_t)intpart;
      if (a == 0)
      {
          *nstrp++ = '0';
          ++nlen;
      }
      else
      {
          while (a != 0)
          {
              b = (int32_t)a / (int32_t)radix;
              c = (int32_t)a - ((int32_t)b * (int32_t)radix);
              if (c < 0)
              {
                  uc = (uint32_t)c;
                  c  = (int32_t)(~uc) + 1 + '0';
              }
              else
              {
                  c = c + '0';
              }
              a        = b;
              *nstrp++ = (char)c;
              ++nlen;
          }
      }
      return nlen;
  }
  #endif /* PRINTF_FLOAT_ENABLE */
  
  /*!
   * brief This function outputs its parameters according to a formatted string.
   *
   * note I/O is performed by calling given function pointer using following
   * (*func_ptr)(c);
   *
   * param[in] fmt_ptr   Format string for printf.
   * param[in] args_ptr  Arguments to printf.
   * param[in] buf  pointer to the buffer
   * param cb print callback function pointer
   *
   * return Number of characters to be print
   */
  int StrFormatPrintf(const char *fmt, va_list ap, char *buf, printfCb cb)
  {
      /* va_list ap; */
      const char *p;
      char c;
  
      char vstr[33];
      char *vstrp  = NULL;
      int32_t vlen = 0;
  
      int32_t count = 0;
  
      uint32_t field_width;
      uint32_t precision_width;
      char *sval;
      int32_t cval;
      bool use_caps;
      uint8_t radix = 0;
  
  #if PRINTF_ADVANCED_ENABLE
      uint32_t flags_used;
      char schar;
      int64_t ival;
      uint64_t uval = 0;
      bool valid_precision_width;
  #else
      int32_t ival;
      uint32_t uval = 0;
  #endif /* PRINTF_ADVANCED_ENABLE */
  
  #if PRINTF_FLOAT_ENABLE
      double fval;
  #endif /* PRINTF_FLOAT_ENABLE */
  
      /* Start parsing apart the format string and display appropriate formats and data. */
      p = fmt;
      while (true)
      {
          if ('\0' == *p)
          {
              break;
          }
          c = *p;
          /*
           * All formats begin with a '%' marker.  Special chars like
           * '\n' or '\t' are normally converted to the appropriate
           * character by the __compiler__.  Thus, no need for this
           * routine to account for the '\' character.
           */
          if (c != '%')
          {
              cb(buf, &count, c, 1);
              p++;
              /* By using 'continue', the next iteration of the loop is used, skipping the code that follows. */
              continue;
          }
  
          use_caps = true;
  
  #if PRINTF_ADVANCED_ENABLE
          /* First check for specification modifier flags. */
          flags_used = PrintCheckFlags(&p);
  #endif /* PRINTF_ADVANCED_ENABLE */
  
          /* Next check for minimum field width. */
          field_width = PrintGetWidth(&p, &ap);
  
          /* Next check for the width and precision field separator. */
  #if PRINTF_ADVANCED_ENABLE
          precision_width = PrintGetPrecision(&p, &ap, &valid_precision_width);
  #else
          precision_width = PrintGetPrecision(&p, &ap, NULL);
          (void)precision_width;
  #endif
  
  #if PRINTF_ADVANCED_ENABLE
          /* Check for the length modifier. */
          flags_used |= PrintGetLengthFlag(&p);
  #endif /* PRINTF_ADVANCED_ENABLE */
  
          /* Now we're ready to examine the format. */
          c = *++p;
          {
              if (1U == PrintIsdi(c))
              {
  #if PRINTF_ADVANCED_ENABLE
                  if (flags_used & kPRINTF_LengthLongLongInt)
                  {
                      ival = (int64_t)va_arg(ap, int64_t);
                  }
                  else
  #endif /* PRINTF_ADVANCED_ENABLE */
                  {
                      ival = (int32_t)va_arg(ap, int32_t);
                  }
                  vlen  = ConvertRadixNumToString(vstr, (void *)&ival, 1, 10, use_caps);
                  vstrp = &vstr[vlen];
  #if PRINTF_ADVANCED_ENABLE
                  vlen += PrintGetSignChar(ival, flags_used, &schar);
                  PrintOutputdifFobpu(flags_used, field_width, vlen, schar, vstrp, cb, buf, &count);
  #else
                  PrintOutputdifFobpu(0U, field_width, (uint32_t)vlen, '\0', vstrp, cb, buf, &count);
  #endif
              }
              else if (1U == PrintIsfF(c))
              {
  #if PRINTF_FLOAT_ENABLE
                  fval  = (double)va_arg(ap, double);
                  vlen  = ConvertFloatRadixNumToString(vstr, &fval, 10, precision_width);
                  vstrp = &vstr[vlen];
  
  #if PRINTF_ADVANCED_ENABLE
                  vlen += PrintGetSignChar((int32_t)fval, flags_used, &schar);
                  PrintOutputdifFobpu(flags_used, field_width, vlen, schar, vstrp, cb, buf, &count);
  #else
                  PrintOutputdifFobpu(0, field_width, vlen, '\0', vstrp, cb, buf, &count);
  #endif
  
  #else
                  (void)va_arg(ap, double);
  #endif /* PRINTF_FLOAT_ENABLE */
              }
              else if (1U == PrintIsxX(c))
              {
                  if (c == 'x')
                  {
                      use_caps = false;
                  }
  #if PRINTF_ADVANCED_ENABLE
                  if (flags_used & kPRINTF_LengthLongLongInt)
                  {
                      uval = (uint64_t)va_arg(ap, uint64_t);
                  }
                  else
  #endif /* PRINTF_ADVANCED_ENABLE */
                  {
                      uval = (uint32_t)va_arg(ap, uint32_t);
                  }
                  vlen  = ConvertRadixNumToString(vstr, &uval, 0, 16, use_caps);
                  vstrp = &vstr[vlen];
  #if PRINTF_ADVANCED_ENABLE
                  PrintOutputxX(flags_used, field_width, vlen, use_caps, vstrp, cb, buf, &count);
  #else
                  PrintOutputxX(0U, field_width, (uint32_t)vlen, use_caps, vstrp, cb, buf, &count);
  #endif
              }
              else if (1U == PrintIsobpu(c))
              {
  #if PRINTF_ADVANCED_ENABLE
                  if (flags_used & kPRINTF_LengthLongLongInt)
                  {
                      uval = (uint64_t)va_arg(ap, uint64_t);
                  }
                  else
  #endif /* PRINTF_ADVANCED_ENABLE */
                  {
                      uval = (uint32_t)va_arg(ap, uint32_t);
                  }
  
                  radix = PrintGetRadixFromobpu(c);
  
                  vlen  = ConvertRadixNumToString(vstr, &uval, 0, (int32_t)radix, use_caps);
                  vstrp = &vstr[vlen];
  #if PRINTF_ADVANCED_ENABLE
                  PrintOutputdifFobpu(flags_used, field_width, vlen, '\0', vstrp, cb, buf, &count);
  #else
                  PrintOutputdifFobpu(0U, field_width, (uint32_t)vlen, '\0', vstrp, cb, buf, &count);
  #endif
              }
              else if (c == 'c')
              {
                  cval = (int32_t)va_arg(ap, uint32_t);
                  cb(buf, &count, cval, 1);
              }
              else if (c == 's')
              {
                  sval = (char *)va_arg(ap, char *);
                  if (NULL != sval)
                  {
  #if PRINTF_ADVANCED_ENABLE
                      if (valid_precision_width)
                      {
                          vlen = precision_width;
                      }
                      else
                      {
                          vlen = strlen(sval);
                      }
  #else
                      vlen = (int32_t)strlen(sval);
  #endif /* PRINTF_ADVANCED_ENABLE */
  #if PRINTF_ADVANCED_ENABLE
                      if (!(flags_used & kPRINTF_Minus))
  #endif /* PRINTF_ADVANCED_ENABLE */
                      {
                          cb(buf, &count, ' ', (int)field_width - (int)vlen);
                      }
  
  #if PRINTF_ADVANCED_ENABLE
                      if (valid_precision_width)
                      {
                          while ((*sval) && (vlen > 0))
                          {
                              cb(buf, &count, *sval++, 1);
                              vlen--;
                          }
                          /* In case that vlen sval is shorter than vlen */
                          vlen = precision_width - vlen;
                      }
                      else
                      {
  #endif /* PRINTF_ADVANCED_ENABLE */
                          while ('\0' != (*sval))
                          {
                              cb(buf, &count, *sval++, 1);
                          }
  #if PRINTF_ADVANCED_ENABLE
                      }
  #endif /* PRINTF_ADVANCED_ENABLE */
  
  #if PRINTF_ADVANCED_ENABLE
                      if (flags_used & kPRINTF_Minus)
                      {
                          cb(buf, &count, ' ', field_width - vlen);
                      }
  #endif /* PRINTF_ADVANCED_ENABLE */
                  }
              }
              else
              {
                  cb(buf, &count, c, 1);
              }
          }
          p++;
      }
  
      return count;
  }
  
  #if SCANF_FLOAT_ENABLE
  static uint8_t StrFormatScanIsFloat(char *c)
  {
      uint8_t ret = 0U;
      if (('a' == (*c)) || ('A' == (*c)) || ('e' == (*c)) || ('E' == (*c)) || ('f' == (*c)) || ('F' == (*c)) ||
          ('g' == (*c)) || ('G' == (*c)))
      {
          ret = 1U;
      }
      return ret;
  }
  #endif
  
  static uint8_t StrFormatScanIsFormatStarting(char *c)
  {
      uint8_t ret = 1U;
      if ((*c != '%'))
      {
          ret = 0U;
      }
      else if (*(c + 1) == '%')
      {
          ret = 0U;
      }
      else
      {
          /*MISRA rule 15.7*/
      }
  
      return ret;
  }
  
  static uint8_t StrFormatScanGetBase(uint8_t base, const char *s)
  {
      if (base == 0U)
      {
          if (s[0] == '0')
          {
              if ((s[1] == 'x') || (s[1] == 'X'))
              {
                  base = 16;
              }
              else
              {
                  base = 8;
              }
          }
          else
          {
              base = 10;
          }
      }
      return base;
  }
  
  static uint8_t StrFormatScanCheckSymbol(const char *p, int8_t *neg)
  {
      uint8_t len;
      switch (*p)
      {
          case '-':
              *neg = -1;
              len  = 1;
              break;
          case '+':
              *neg = 1;
              len  = 1;
              break;
          default:
              *neg = 1;
              len  = 0;
              break;
      }
      return len;
  }
  
  static uint8_t StrFormatScanFillInteger(uint32_t flag, va_list *args_ptr, int32_t val)
  {
  #if SCANF_ADVANCED_ENABLE
      if ((flag & kSCANF_Suppress))
      {
          return 0u;
      }
  
      switch (flag & kSCANF_LengthMask)
      {
          case kSCANF_LengthChar:
              if (0 != (flag & (uint32_t)kSCANF_TypeSinged))
              {
                  *va_arg(*args_ptr, signed char *) = (signed char)val;
              }
              else
              {
                  *va_arg(*args_ptr, unsigned char *) = (unsigned char)val;
              }
              break;
          case kSCANF_LengthShortInt:
              if (0 != (flag & (uint32_t)kSCANF_TypeSinged))
              {
                  *va_arg(*args_ptr, signed short *) = (signed short)val;
              }
              else
              {
                  *va_arg(*args_ptr, unsigned short *) = (unsigned short)val;
              }
              break;
          case kSCANF_LengthLongInt:
              if (0 != (flag & (uint32_t)kSCANF_TypeSinged))
              {
                  *va_arg(*args_ptr, signed long int *) = (signed long int)val;
              }
              else
              {
                  *va_arg(*args_ptr, unsigned long int *) = (unsigned long int)val;
              }
              break;
          case kSCANF_LengthLongLongInt:
              if (0 != (flag & (uint32_t)kSCANF_TypeSinged))
              {
                  *va_arg(*args_ptr, signed long long int *) = (signed long long int)val;
              }
              else
              {
                  *va_arg(*args_ptr, unsigned long long int *) = (unsigned long long int)val;
              }
              break;
          default:
              /* The default type is the type int. */
              if (0 != (flag & (uint32_t)kSCANF_TypeSinged))
              {
                  *va_arg(*args_ptr, signed int *) = (signed int)val;
              }
              else
              {
                  *va_arg(*args_ptr, unsigned int *) = (unsigned int)val;
              }
              break;
      }
  #else
      /* The default type is the type int. */
      if (0U != (flag & (uint32_t)kSCANF_TypeSinged))
      {
          *va_arg(*args_ptr, signed int *) = (signed int)val;
      }
      else
      {
          *va_arg(*args_ptr, unsigned int *) = (unsigned int)val;
      }
  #endif /* SCANF_ADVANCED_ENABLE */
  
      return 1u;
  }
  
  #if SCANF_FLOAT_ENABLE
  static uint8_t StrFormatScanFillFloat(uint32_t flag, va_list *args_ptr, double fnum)
  {
  #if SCANF_ADVANCED_ENABLE
      if (0U != (flag & (uint32_t)kSCANF_Suppress))
      {
          return 0u;
      }
      else
  #endif /* SCANF_ADVANCED_ENABLE */
      {
          if (0U != (flag & (uint32_t)kSCANF_LengthLongLongDouble))
          {
              *va_arg(*args_ptr, double *) = fnum;
          }
          else
          {
              *va_arg(*args_ptr, float *) = (float)fnum;
          }
          return 1u;
      }
  }
  #endif /* SCANF_FLOAT_ENABLE */
  
  static uint8_t StrFormatScanfStringHandling(char **str, uint32_t *flag, uint32_t *field_width, uint8_t *base)
  {
      uint8_t exitPending = 0U;
      char *c             = *str;
  
      /* Loop to get full conversion specification. */
      while (('\0' != (*c)) && (0U == (*flag & (uint32_t)kSCANF_DestMask)))
      {
  #if SCANF_ADVANCED_ENABLE
          if ('*' == (*c))
          {
              if (0U != ((*flag) & (uint32_t)kSCANF_Suppress))
              {
                  /* Match failure. */
                  exitPending = 1U;
              }
              else
              {
                  (*flag) |= (uint32_t)kSCANF_Suppress;
              }
          }
          else if ('h' == (*c))
          {
              if (0U != ((*flag) & (uint32_t)kSCANF_LengthMask))
              {
                  /* Match failure. */
                  exitPending = 1U;
              }
              else
              {
                  if (c[1] == 'h')
                  {
                      (*flag) |= (uint32_t)kSCANF_LengthChar;
                      c++;
                  }
                  else
                  {
                      (*flag) |= (uint32_t)kSCANF_LengthShortInt;
                  }
              }
          }
          else if ('l' == (*c))
          {
              if (0U != ((*flag) & (uint32_t)kSCANF_LengthMask))
              {
                  /* Match failure. */
                  exitPending = 1U;
              }
              else
              {
                  if (c[1] == 'l')
                  {
                      (*flag) |= (uint32_t)kSCANF_LengthLongLongInt;
                      c++;
                  }
                  else
                  {
                      (*flag) |= (uint32_t)kSCANF_LengthLongInt;
                  }
              }
          }
          else
  #endif /* SCANF_ADVANCED_ENABLE */
  #if SCANF_FLOAT_ENABLE
              if ('L' == (*c))
          {
              if (0U != ((*flag) & (uint32_t)kSCANF_LengthMask))
              {
                  /* Match failure. */
                  exitPending = 1U;
              }
              else
              {
                  (*flag) |= (uint32_t)kSCANF_LengthLongLongDouble;
              }
          }
          else
  #endif /* SCANF_FLOAT_ENABLE */
              if (((*c) >= '0') && ((*c) <= '9'))
          {
              {
                  char *p;
                  (*field_width) = strtoul(c, &p, 10);
                  c              = p - 1;
              }
          }
          else if ('d' == (*c))
          {
              (*base) = 10U;
              (*flag) |= (uint32_t)kSCANF_TypeSinged;
              (*flag) |= (uint32_t)kSCANF_DestInt;
          }
          else if ('u' == (*c))
          {
              (*base) = 10U;
              (*flag) |= (uint32_t)kSCANF_DestInt;
          }
          else if ('o' == (*c))
          {
              (*base) = 8U;
              (*flag) |= (uint32_t)kSCANF_DestInt;
          }
          else if (('x' == (*c)))
          {
              (*base) = 16U;
              (*flag) |= (uint32_t)kSCANF_DestInt;
          }
          else if ('X' == (*c))
          {
              (*base) = 16U;
              (*flag) |= (uint32_t)kSCANF_DestInt;
          }
          else if ('i' == (*c))
          {
              (*base) = 0U;
              (*flag) |= (uint32_t)kSCANF_DestInt;
          }
  #if SCANF_FLOAT_ENABLE
          else if (1 == StrFormatScanIsFloat(c))
          {
              (*flag) |= (uint32_t)kSCANF_DestFloat;
          }
  #endif /* SCANF_FLOAT_ENABLE */
          else if ('c' == (*c))
          {
              (*flag) |= (uint32_t)kSCANF_DestChar;
              if (MAX_FIELD_WIDTH == (*field_width))
              {
                  (*field_width) = 1;
              }
          }
          else if ('s' == (*c))
          {
              (*flag) |= (uint32_t)kSCANF_DestString;
          }
          else
          {
              exitPending = 1U;
          }
  
          if (1U == exitPending)
          {
              break;
          }
          else
          {
              c++;
          }
      }
      *str = c;
      return exitPending;
  }
  
  /*!
   * brief Converts an input line of ASCII characters based upon a provided
   * string format.
   *
   * param[in] line_ptr The input line of ASCII data.
   * param[in] format   Format first points to the format string.
   * param[in] args_ptr The list of parameters.
   *
   * return Number of input items converted and assigned.
   * retval IO_EOF When line_ptr is empty string "".
   */
  int StrFormatScanf(const char *line_ptr, char *format, va_list args_ptr)
  {
      uint8_t base;
      int8_t neg;
      /* Identifier for the format string. */
      char *c = format;
      char *buf;
      /* Flag telling the conversion specification. */
      uint32_t flag = 0;
      /* Filed width for the matching input streams. */
      uint32_t field_width;
      /* How many arguments are assigned except the suppress. */
      uint32_t nassigned = 0;
      /* How many characters are read from the input streams. */
      uint32_t n_decode = 0;
  
      int32_t val;
  
      uint8_t added;
  
      uint8_t exitPending = 0;
  
      const char *s;
      /* Identifier for the input string. */
      const char *p = line_ptr;
  
  #if SCANF_FLOAT_ENABLE
      double fnum = 0.0;
  #endif /* SCANF_FLOAT_ENABLE */
      /* Return EOF error before any conversion. */
      if (*p == '\0')
      {
          return -1;
      }
  
      /* Decode directives. */
      while (('\0' != (*c)) && ('\0' != (*p)))
      {
          /* Ignore all white-spaces in the format strings. */
          if (0U != ScanIgnoreWhiteSpace((const char **)((void *)&c)))
          {
              n_decode += ScanIgnoreWhiteSpace(&p);
          }
          else if (0U == StrFormatScanIsFormatStarting(c))
          {
              /* Ordinary characters. */
              c++;
              if (*p == *c)
              {
                  n_decode++;
                  p++;
                  c++;
              }
              else
              {
                  /* Match failure. Misalignment with C99, the unmatched characters need to be pushed back to stream.
                   * However, it is deserted now. */
                  break;
              }
          }
          else
          {
              /* convernsion specification */
              c++;
              /* Reset. */
              flag        = 0;
              field_width = MAX_FIELD_WIDTH;
              base        = 0;
              added       = 0U;
  
              exitPending = StrFormatScanfStringHandling(&c, &flag, &field_width, &base);
  
              if (1U == exitPending)
              {
                  /* Format strings are exhausted. */
                  break;
              }
  
              /* Matching strings in input streams and assign to argument. */
              if ((flag & (uint32_t)kSCANF_DestMask) == (uint32_t)kSCANF_DestChar)
              {
                  s   = (const char *)p;
                  buf = va_arg(args_ptr, char *);
                  while ((0U != (field_width--))
  #if SCANF_ADVANCED_ENABLE
                         && ('\0' != (*p))
  #endif
                  )
                  {
  #if SCANF_ADVANCED_ENABLE
                      if (flag & kSCANF_Suppress)
                      {
                          p++;
                      }
                      else
  #endif
                      {
                          *buf++ = *p++;
  #if SCANF_ADVANCED_ENABLE
                          added = 1u;
  #endif
                      }
                      n_decode++;
                  }
  
  #if SCANF_ADVANCED_ENABLE
                  if (1u == added)
  #endif
                  {
                      nassigned++;
                  }
              }
              else if ((flag & (uint32_t)kSCANF_DestMask) == (uint32_t)kSCANF_DestString)
              {
                  n_decode += ScanIgnoreWhiteSpace(&p);
                  s   = p;
                  buf = va_arg(args_ptr, char *);
                  while ((0U != (field_width--)) && (*p != '\0') && (0U == ScanIsWhiteSpace(*p)))
                  {
  #if SCANF_ADVANCED_ENABLE
                      if (flag & kSCANF_Suppress)
                      {
                          p++;
                      }
                      else
  #endif
                      {
                          *buf++ = *p++;
  #if SCANF_ADVANCED_ENABLE
                          added = 1u;
  #endif
                      }
                      n_decode++;
                  }
  
  #if SCANF_ADVANCED_ENABLE
                  if (1u == added)
  #endif
                  {
                      /* Add NULL to end of string. */
                      *buf = '\0';
                      nassigned++;
                  }
              }
              else if ((flag & (uint32_t)kSCANF_DestMask) == (uint32_t)kSCANF_DestInt)
              {
                  n_decode += ScanIgnoreWhiteSpace(&p);
                  s    = p;
                  val  = 0;
                  base = StrFormatScanGetBase(base, s);
  
                  added = StrFormatScanCheckSymbol(p, &neg);
                  n_decode += added;
                  p += added;
                  field_width -= added;
  
                  s = p;
                  if (strlen(p) > field_width)
                  {
                      char temp[12];
                      char *tempEnd;
                      (void)memcpy(temp, p, sizeof(temp) - 1U);
                      temp[sizeof(temp) - 1U] = '\0';
                      val                     = (int32_t)strtoul(temp, &tempEnd, (int)base);
                      p                       = p + (tempEnd - temp);
                  }
                  else
                  {
                      char *tempEnd;
                      val = (int32_t)strtoul(p, &tempEnd, (int)base);
                      p   = tempEnd;
                  }
                  n_decode += (uint32_t)p - (uint32_t)s;
  
                  val *= neg;
  
                  nassigned += StrFormatScanFillInteger(flag, &args_ptr, val);
              }
  #if SCANF_FLOAT_ENABLE
              else if ((flag & kSCANF_DestMask) == kSCANF_DestFloat)
              {
                  n_decode += ScanIgnoreWhiteSpace(&p);
                  fnum = strtod(p, (char **)&s);
  
                  if ((fnum < HUGE_VAL) && (fnum > -HUGE_VAL))
                  {
                      n_decode += (int)(s) - (int)(p);
                      p = s;
                      nassigned += StrFormatScanFillFloat(flag, &args_ptr, fnum);
                  }
              }
  #endif /* SCANF_FLOAT_ENABLE */
              else
              {
                  break;
              }
          }
      }
      return (int)nassigned;
  }
  