Skip to content
Snippets Groups Projects
lib_libvsprintf.c 37.1 KiB
Newer Older
patacongo's avatar
patacongo committed

patacongo's avatar
patacongo committed
/****************************************************************************
patacongo's avatar
patacongo committed
 ****************************************************************************/
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
static void prejustify(FAR struct lib_stream_s *obj, ubyte fmt,
                       ubyte flags, int fieldwidth, int numwidth)
{
  int i;

  switch (fmt)
    {
      default:
      case FMT_RJUST:
        if (IS_SIGNED(flags))
          {
            numwidth++;
          }

        for (i = fieldwidth - numwidth; i > 0; i--)
          {
            obj->put(obj, ' ');
          }

        if (IS_NEGATE(flags))
          {
            obj->put(obj, '-');
          }
        else if (IS_SHOWPLUS(flags))
          {
            obj->put(obj, '+');
          }
        break;

      case FMT_RJUST0:
         if (IS_NEGATE(flags))
          {
            obj->put(obj, '-');
            numwidth++;
          }
        else if (IS_SHOWPLUS(flags))
          {
            obj->put(obj, '+');
            numwidth++;
          }

        for (i = fieldwidth - numwidth; i > 0; i--)
          {
            obj->put(obj, '0');
          }
        break;

      case FMT_LJUST:
         if (IS_NEGATE(flags))
          {
            obj->put(obj, '-');
          }
        else if (IS_SHOWPLUS(flags))
          {
            obj->put(obj, '+');
          }
        break;
    }
}
patacongo's avatar
patacongo committed
/****************************************************************************
patacongo's avatar
patacongo committed
 ****************************************************************************/
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
static void postjustify(FAR struct lib_stream_s *obj, ubyte fmt,
                        ubyte flags, int fieldwidth, int numwidth)
{
  int i;

  /* Apply field justification to the integer value. */

  switch (fmt)
    {
      default:
      case FMT_RJUST:
      case FMT_RJUST0:
        break;

      case FMT_LJUST:
        if (IS_SIGNED(flags))
          {
            numwidth++;
          }

        for (i = fieldwidth - numwidth; i > 0; i--)
          {
            obj->put(obj, ' ');
          }
        break;
    }
}
patacongo's avatar
patacongo committed
/****************************************************************************
patacongo's avatar
patacongo committed
 * Public Functions
patacongo's avatar
patacongo committed
 ****************************************************************************/
patacongo's avatar
patacongo committed

patacongo's avatar
patacongo committed
/****************************************************************************
patacongo's avatar
patacongo committed
 * lib_vsprintf
patacongo's avatar
patacongo committed
 ****************************************************************************/
patacongo's avatar
patacongo committed

int lib_vsprintf(FAR struct lib_stream_s *obj, const char *src, va_list ap)
patacongo's avatar
patacongo committed
{
  char           *ptmp;
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
  int             width;
  int             trunc;
  ubyte           fmt;
#endif
  ubyte           flags;
patacongo's avatar
patacongo committed

  for (; *src; src++)
    {
      /* Just copy regular characters */

      if (*src != '%')
        {
           obj->put(obj, *src);
patacongo's avatar
patacongo committed
        }

      /* We have found a format specifier. Move past it. */

      src++;

      /* Assume defaults */

      flags = 0;
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
      fmt   = FMT_RJUST;
      width = 0;
      trunc = 0;
#endif

      /* Process each format qualifier. */

      for (; *src; src++)
patacongo's avatar
patacongo committed
        {
          /* Break out of the loop when the format is known. */
patacongo's avatar
patacongo committed

patacongo's avatar
patacongo committed

patacongo's avatar
patacongo committed

          else if (*src == '-')
            {
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
              fmt = FMT_LJUST;
#endif
            }

          /* Check for leading zero fill right justification. */

          else if (*src == '0')
            {
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
              fmt = FMT_RJUST0;
#endif
            }
#if 0
          /* Center justification. */
patacongo's avatar
patacongo committed

patacongo's avatar
patacongo committed
            {
patacongo's avatar
patacongo committed

          else if (*src == '*')
            {
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
              int value = va_arg(ap, int);
              if (IS_HASDOT(flags))
patacongo's avatar
patacongo committed
                {
patacongo's avatar
patacongo committed
                }
patacongo's avatar
patacongo committed
                {
patacongo's avatar
patacongo committed
                }
patacongo's avatar
patacongo committed

patacongo's avatar
patacongo committed

          else if (*src >= '1' && *src <= '9')
            {
#ifdef CONFIG_NOPRINTF_FIELDWIDTH
              for (src++; (*src >= '0' && *src <= '9'); src++);
#else
              /* Accumulate the field width integer. */

              int n = ((int)(*src)) - (int)'0';
              for (src++; (*src >= '0' && *src <= '9'); src++)
patacongo's avatar
patacongo committed
                {
patacongo's avatar
patacongo committed
                }

patacongo's avatar
patacongo committed
                {
patacongo's avatar
patacongo committed
                }
patacongo's avatar
patacongo committed
                {
patacongo's avatar
patacongo committed
                }
patacongo's avatar
patacongo committed

patacongo's avatar
patacongo committed

patacongo's avatar
patacongo committed

          else if (*src == '.')
            {
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
              SET_HASDOT(flags);
#endif
            }
patacongo's avatar
patacongo committed

patacongo's avatar
patacongo committed

patacongo's avatar
patacongo committed

patacongo's avatar
patacongo committed

patacongo's avatar
patacongo committed

      /* "%%" means that a literal '%' was intended (instead of a format
       * specification).
       */
patacongo's avatar
patacongo committed

patacongo's avatar
patacongo committed

patacongo's avatar
patacongo committed

      if (*src == 's')
        {
          /* Just concatenate the string into the output */
patacongo's avatar
patacongo committed

          ptmp = va_arg(ap, char *);
          if (!ptmp)
            {
              ptmp = (char*)g_nullstring;
patacongo's avatar
patacongo committed
            }

patacongo's avatar
patacongo committed

      /* Check for the character output */

      else if (*src == 'c')
        {
          /* Just copy the character into the output. */

          int n = va_arg(ap, int);
          obj->put(obj, n);
          continue;
        }

      /* Check for the long long prefix. */

      if (*src == 'L')
        {
           SET_LONGLONGPRECISION(flags);
           ++src;
        }
      else if (*src == 'l')
        {
          SET_LONGPRECISION(flags);
          if (*++src == 'l')
patacongo's avatar
patacongo committed
            {
patacongo's avatar
patacongo committed
            }
patacongo's avatar
patacongo committed

patacongo's avatar
patacongo committed

      if (strchr("diuxXpob", *src))
        {
#ifdef CONFIG_HAVE_LONG_LONG
          if (IS_LONGLONGPRECISION(flags) && *src != 'p')
patacongo's avatar
patacongo committed
            {
              long long lln;
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
              int lluwidth;
#endif
              /* Extract the long long value. */
patacongo's avatar
patacongo committed

patacongo's avatar
patacongo committed

#ifdef CONFIG_NOPRINTF_FIELDWIDTH
              /* Output the number */

              llutoascii(obj, *src, flags, (unsigned long long)lln);
#else
              /* Resolve sign-ness and format issues */

              llfixup(*src, &flags, &lln);

              /* Get the width of the output */

              lluwidth = getllusize(*src, flags, lln);

              /* Perform left field justification actions */

              prejustify(obj, fmt, flags, width, lluwidth);

              /* Output the number */

              llutoascii(obj, *src, flags, (unsigned long long)lln);

              /* Perform right field justification actions */

              postjustify(obj, fmt, flags, width, lluwidth);
#endif
patacongo's avatar
patacongo committed
            }
          else
#endif /* CONFIG_HAVE_LONG_LONG */
#ifdef CONFIG_LONG_IS_NOT_INT
          if (IS_LONGPRECISION(flags) && *src != 'p')
            {
              long ln;
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
              int luwidth;
#endif
              /* Extract the long value. */

              ln = va_arg(ap, long);

#ifdef CONFIG_NOPRINTF_FIELDWIDTH
              /* Output the number */

              lutoascii(obj, *src, flags, (unsigned long)ln);
#else
              /* Resolve sign-ness and format issues */

              lfixup(*src, &flags, &ln);

              /* Get the width of the output */

              luwidth = getlusize(*src, flags, ln);

              /* Perform left field justification actions */
patacongo's avatar
patacongo committed

patacongo's avatar
patacongo committed

              /* Output the number */

              lutoascii(obj, *src, flags, (unsigned long)ln);

              /* Perform right field justification actions */

              postjustify(obj, fmt, flags, width, luwidth);
#endif
            }
          else
#endif /* CONFIG_LONG_IS_NOT_INT */
#ifdef CONFIG_PTR_IS_NOT_INT
          if (*src == 'p')
patacongo's avatar
patacongo committed
            {
              /* Extract the integer value. */
patacongo's avatar
patacongo committed

              p = va_arg(ap, void *);

#ifdef CONFIG_NOPRINTF_FIELDWIDTH
              /* Output the pointer value */

              ptohex(obj, flags, p);
#else
              /* Resolve sign-ness and format issues */

              lfixup(*src, &flags, &ln);

              /* Get the width of the output */

              luwidth = getpsize(*src, flags, p);

              /* Perform left field justification actions */

              prejustify(obj, fmt, flags, width, pwidth);

              /* Output the pointer value */

              ptohex(obj, flags, p);

              /* Perform right field justification actions */

              postjustify(obj, fmt, flags, width, pwidth);
#endif
patacongo's avatar
patacongo committed
            }
          else
patacongo's avatar
patacongo committed
            {
              int n;
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
              int uwidth;
#endif
              /* Extract the long long value. */
patacongo's avatar
patacongo committed

patacongo's avatar
patacongo committed

#ifdef CONFIG_NOPRINTF_FIELDWIDTH
              /* Output the number */
patacongo's avatar
patacongo committed

              utoascii(obj, *src, flags, (unsigned int)n);
#else
              /* Resolve sign-ness and format issues */
patacongo's avatar
patacongo committed

patacongo's avatar
patacongo committed

patacongo's avatar
patacongo committed

              uwidth = getusize(*src, flags, n);

              /* Perform left field justification actions */

              prejustify(obj, fmt, flags, width, uwidth);

              /* Output the number */

              utoascii(obj, *src, flags, (unsigned int)n);

              /* Perform right field justification actions */

              postjustify(obj, fmt, flags, width, uwidth);
#endif
patacongo's avatar
patacongo committed
            }
        }

      /* Handle floating point conversions */

      else if (strchr("eEfgG", *src))
        {
patacongo's avatar
patacongo committed
#ifdef CONFIG_CPP_HAVE_WARNING
#  warning "No floating point support"
#endif
patacongo's avatar
patacongo committed
    }

  return obj->nput;
}