/* ###################################################################
**     This component module is generated by Processor Expert. Do not modify it.
**     Filename    : McuXFormat.h
**     Project     : FRDM-K64F_Generator
**     Processor   : MK64FN1M0VLL12
**     Component   : XFormat
**     Version     : Component 01.026, Driver 01.00, CPU db: 3.00.000
**     Compiler    : GNU C Compiler
**     Date/Time   : 2020-11-23, 10:16, # CodeGen: 715
**     Abstract    :
**
**     Settings    :
**
**     Contents    :
**         xvformat  - unsigned McuXFormat_xvformat(void (*outchar)(void *,char), void *arg, const...
**         xformat   - unsigned McuXFormat_xformat(void (*outchar)(void *,char), void *arg, const...
**         xsprintf  - int McuXFormat_xsprintf(char *buf, const char *fmt, ...);
**         xsnprintf - int McuXFormat_xsnprintf(char *buf, size_t max_len, const char *fmt, ...);
**         Deinit    - void McuXFormat_Deinit(void);
**         Init      - void McuXFormat_Init(void);
**
** *  Copyright : (c) Copyright Mario Viara, 2014-2020, https://github.com/MarioViara/xprintfc
**  * Adopted for Processor Expert: Erich Styger
**  * xsnprintf() contributed by Engin Lee
**  * Web:         https://mcuoneclipse.com
**  * SourceForge: https://sourceforge.net/projects/mcuoneclipse
**  * Git:         https://github.com/ErichStyger/McuOnEclipse_PEx
**  * All rights reserved.
**  *
**  * Redistribution and use in source and binary forms, with or without modification,
**  * are permitted provided that the following conditions are met:
**  *
**  * - Redistributions of source code must retain the above copyright notice, this list
**  *   of conditions and the following disclaimer.
**  *
**  * - Redistributions in binary form must reproduce the above copyright notice, this
**  *   list of conditions and the following disclaimer in the documentation and/or
**  *   other materials provided with the distribution.
**  *
**  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
**  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
**  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
**  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
**  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
**  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
**  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
**  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
**  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
**  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
** ###################################################################*/
/*!
** @file McuXFormat.h
** @version 01.00
** @brief
**
*/         
/*!
**  @addtogroup McuXFormat_module McuXFormat module documentation
**  @{
*/         

/* MODULE McuXFormat. */
/**
 * @file  xformatc.c
 *
 * @brief Printf C implementation.
 *
 * Tested wuth the following operating systems / compilers :
 *
 * - Visual studio 6
 * - Visual studio 2008 / Windows CE
 * - MinGw 32
 * - Linux i686
 * - Linux x86_64
 * - GCC wiith embedded ARM.
 * - Linux armel
 * - HCS08 with Freescale compiler.
 * - SDCC (Z80 and 8051)
 *
 * @author  Mario Viara
 *
 *
 * @copyright Copyright Mario Viara 2014  - License Open Source (LGPL)
 * This is a free software and is opened for education, research and commercial
 * developments under license policy of following terms:
 *
 * - This is a free software and there is NO WARRANTY.
 * - No restriction on use. You can use, modify and redistribute it for personal,
 *   non-profit or commercial product UNDER YOUR RESPONSIBILITY.
 * - Redistributions of source code must retain the above copyright notice.
 *
 * To contact the author send an email to mario_at_viara.eu
 *
 */
#include "McuXFormat.h"

/**
 * Default largest int is long
 */
#ifndef LONG
#define LONG  long
#endif

/**
 * Define the double type if not defined
 */
#ifndef DOUBLE
#define DOUBLE  double
#endif


/**
 * Default long long type
 */
#ifndef LONGLONG
#define LONGLONG   long long
#endif


/**
 * Definition to convert integer part of floating point
 * number if supported we use the long long type
 */
#if XCFG_FORMAT_LONGLONG
#define FLOAT_LONG    LONGLONG
#define FLOAT_VALUE   llvalue
#define FLOAT_TYPE    FLAG_TYPE_LONGLONG
#else
#define FLOAT_LONG    LONG
#define FLOAT_VALUE   lvalue
#define FLOAT_TYPE    FLAG_TYPE_LONG
#endif

/**
 * Structure with all parameter used
 */
struct param_s
{
  /**
   * Buffer for current integer value and for temporary
   * double value defined as union to save stack.
   */
  union
  {
    unsigned LONG   lvalue;
#if XCFG_FORMAT_LONGLONG
    unsigned LONGLONG llvalue;
#endif
#if XCFG_FORMAT_FLOAT
    DOUBLE        dvalue;
#endif
  } values;

  /**
   * Pointer to the output buffer
   */
  char*   out;

#if XCFG_FORMAT_FLOAT
  /**
   * Floating point argument
   */
  DOUBLE    dbl;

  /**
   * Integer part of floating point
   */
  unsigned FLOAT_LONG iPart;

#endif


  /**
   * Current length of the output buffer
   */
  int   length;

  /**
   * Field precision
   */
  int   prec;

  /**
   * Field width
   */
  int   width;


  /**
   * Count the number of char emitted
   */
  unsigned  count;


  /**
   * Parser flags
   */
  unsigned flags;

#define FLAG_TYPE_INT   0x0000  /* Argument is integer          */
#define FLAG_TYPE_LONG    0x0001  /* Argument is long           */
#define FLAG_TYPE_SIZEOF  0x0002  /* Argument is size_t         */
#define FLAG_TYPE_LONGLONG  0x0003  /* Argument is long long        */
#define FLAG_TYPE_MASK    0x0003  /* Mask for field type          */
#define FLAG_PREC     0x0004  /* Precision set            */
#define FLAG_LEFT     0x0008  /* Left alignment           */
#define FLAG_BLANK      0x0010  /* Blank before positive integer number */
#define FLAG_PREFIX     0x0020  /* Prefix required            */
#define FLAG_PLUS     0x0040  /* Force a + before positive number   */
#define FLAG_UPPER      0x0080  /* Output in upper case letter      */
#define FLAG_DECIMAL    0x0100  /* Decimal field            */
#define FLAG_INTEGER    0x0200  /* Integer field            */
#define FLAG_MINUS      0x0400  /* Field is negative          */
#define FLAG_VALUE      0x0800  /* Value set              */
#define FLAG_BUFFER     0x1000  /* Buffer set             */

  /**
   * Length of the prefix
   */
  int   prefixlen;

  /* Buffer to store the field  prefix */
  char prefix[2];


  /** Buffer to store the biggest integer number in binary */
#if XCFG_FORMAT_LONGLONG
  char    buffer[sizeof(LONGLONG)*8+1];
#else
  char    buffer[sizeof(LONG)*8+1];
#endif

  /* Radix for ASCII integer conversion */
  unsigned char radix;

  /* char used for padding */
  char    pad;


  /**
   * Current state
   */
  char    state;

};


/**
 * Enum for the internal state machine
 */
enum State
{
  /* Normal state outputting literal */
  ST_NORMAL = 0,
  /* Just read % */
  ST_PERCENT = 1,

  /* Just read flag */
  ST_FLAG = 2,

  /* Just read the width */
  ST_WIDTH = 3,

  /* Just read '.' */
  ST_DOT= 4,

  /* Just read the precision */
  ST_PRECIS = 5,

  /* Just  read the size */
  ST_SIZE = 6,

  /* Just read the type specifier */
  ST_TYPE = 7
};

/**
 * Enum for char class
 */
enum CharClass
{
  /* Other char */
  CH_OTHER = 0,
  /* The % char */
  CH_PERCENT = 1,
  /* The . char */
  CH_DOT = 2,
  /* The * char */
  CH_STAR = 3,
  /* The 0 char */
  CH_ZERO = 4,
  /* Digit 0-9 */
  CH_DIGIT = 5,
  /* Flag chars */
  CH_FLAG = 6,
  /* Size chars */
  CH_SIZE = 7,
  /* Type chars */
  CH_TYPE = 8
};



/**
 * String used when %s is a null parameter
 */
static const char  ms_null[] = "(null)";
/*
 * String for true value
 */
static const char  ms_true[] = "True";

/**
 * String for false value
 */
static const char  ms_false[]= "False";


/*
 * Digit values
 */
static const char ms_digits[] = "0123456789abcdef";


/*
 * This table contains the next state for all char and it will be
 * generate using xformattable.c
 */

static const unsigned char formatStates[] =
{
  0x06,0x00,0x00,0x06,0x00,0x01,0x00,0x00,
  0x10,0x00,0x03,0x06,0x00,0x06,0x02,0x10,
  0x04,0x45,0x45,0x45,0x45,0x05,0x05,0x05,
  0x05,0x35,0x30,0x00,0x50,0x60,0x00,0x00,
  0x00,0x20,0x28,0x38,0x50,0x50,0x00,0x00,
  0x00,0x30,0x30,0x30,0x50,0x50,0x00,0x00,
  0x08,0x20,0x20,0x28,0x20,0x20,0x20,0x00,
  0x08,0x60,0x60,0x60,0x60,0x60,0x60,0x00,
  0x00,0x70,0x78,0x78,0x78,0x70,0x78,0x00,
  0x07,0x08,0x00,0x00,0x07,0x00,0x28,0x08,
  0x08,0x00,0x00,0x08,0x00,0x08,0x00,0x00,
  0x08,0x00,0x07
};




/**
 * Convert an unsigned value in one string
 *
 * All parameter are in the passed structure
 *
 * @param prec    - Minimum precision
 * @param lvalue  - Unsigned value
 * @param radix   - Radix (Supported values 2/8/10/16)
 *
 * @param out   - Buffer with the converted value.
 */
static void ulong2a(struct param_s * param)
{
  unsigned char digit;

  while (param->prec -- > 0 ||  param->values.lvalue)
  {
    switch (param->radix)
    {
      case 2:
        digit = (unsigned char)(param->values.lvalue & 0x01);
        param->values.lvalue >>= 1;
        break;

      case 8:
        digit = (unsigned char)(param->values.lvalue & 0x07);
        param->values.lvalue >>= 3;
        break;

      case 16:
        digit = (unsigned char)(param->values.lvalue & 0x0F);
        param->values.lvalue >>= 4;
        break;

      default:
      case 10:
        digit = (unsigned char)(param->values.lvalue % 10);
        param->values.lvalue /= 10;
        break;
    }
    *param->out -- = ms_digits[digit];
    param->length ++;
  }
}


#if XCFG_FORMAT_LONGLONG
#ifdef XCFG_FORMAT_LONG_ARE_LONGLONG
#define ullong2a  ulong2a
#else
static void ullong2a(struct param_s * param)
{
  unsigned char digit;

  while (param->prec -- > 0 ||  param->values.llvalue)
  {
    switch (param->radix)
    {
      case 2:
        digit = param->values.llvalue & 0x01;
        param->values.llvalue >>= 1;
        break;

      case 8:
        digit = param->values.llvalue & 0x07;
        param->values.llvalue >>= 3;
        break;

      case 16:
        digit = param->values.llvalue & 0x0F;
        param->values.llvalue >>= 4;
        break;

      default:
      case 10:
        digit = param->values.llvalue % 10;
        param->values.llvalue /= 10;

        break;
    }


    *param->out -- = ms_digits[digit];
    param->length ++;

  }

}
#endif
#endif

#if 1 /* << EST */
typedef struct {
  char *s;
  size_t space;
} StrOutBuffer;

static void putCharIntoBufMaxLen(void *arg, char c) {
  StrOutBuffer *buff = (StrOutBuffer*)arg;
  if (buff->space > 0) {
    buff->space--;
    *(buff->s)++ = c;
  }
}

int xsnprintf(char *buf, size_t max_len, const char *fmt, va_list args) {
  int res = -1;
  StrOutBuffer out;

  out.space = max_len;
  out.s = buf;
  if (max_len <= 1) {
    *buf = 0;
    return 0;
  } else {
    out.space--; /* teminal zero*/
  }
  res = (int)McuXFormat_xvformat(putCharIntoBufMaxLen, (void *)&out, fmt, args);
  *(out.s) = 0;
  if (res > 0) {
    res = out.s - buf;
  }
  return res;
}
#endif

/*
** ===================================================================
**     Method      :  xformat (component XFormat)
**
**     Description :
**         Printf() like function using variable arguments
**     Parameters  :
**         NAME            - DESCRIPTION
**         outchar         - Function pointer to output one new
**                           character
**         arg             - Argument for the output function
**         fmt             - Format options for the list of parameters
**         openArgList     - Open argument list
**     Returns     :
**         ---             - Error code
** ===================================================================
*/
/**
 * Printf like using variable arguments.
 *
 * @param outchar - Pointer to the function to output one new char.
 * @param arg - Argument for the output function.
 * @param fmt - Format options for the list of parameters.
 * @param ... - Arguments
 *
 * @return The number of char emitted.
 *
 * @see xvformat
 */
unsigned McuXFormat_xformat(void (*outchar)(void *,char), void *arg, const char * fmt, ...)
{
  va_list list;
  unsigned count;

  va_start(list,fmt);
  count = McuXFormat_xvformat(outchar,arg,fmt,list);
  va_end(list);
  return count;
}

/*
** ===================================================================
**     Method      :  xvformat (component XFormat)
**
**     Description :
**         Printf() like format function
**     Parameters  :
**         NAME            - DESCRIPTION
**         outchar         - Function pointer to the function
**                           to output one char.
**       * arg             - Argument for the output function.
**         fmt             - Format options for the list of parameters.
**         args            - List of parameters
**     Returns     :
**         ---             - Error code
** ===================================================================
*/

/**
 * We do not want use any library function.
 *
 * @param s - C  string
 * @return The length of the string
 */
static unsigned xstrlen(const char *s)
{
  const char *i;

  for (i = s ; *i ; i++)
  {
  }
  return (unsigned)(i - s);
}

static unsigned outBuffer(void (*myoutchar)(void *arg,char),void *arg,const char *buffer,int len,unsigned  toupper)
{
  unsigned count = 0;
  int i;
  char c;

  for (i = 0; i < len ; i++)
  {
    c = buffer[i];

    if (toupper && (c >= 'a' && c <= 'z'))
    {
      c -= 'a' - 'A';
    }

    (*myoutchar)(arg,c);
    count++;
  }

  return count;
}

static unsigned outChars(void (*myoutchar)(void *arg,char),void *arg,char ch,int len)
{
  unsigned count= 0;

  while (len-- > 0)
  {
    (*myoutchar)(arg,ch);
    count++;
  }

  return count;
}

#if 1 /* << EST added xsprintf() */
static void putCharIntoBuf(void *arg, char c) {
  char **s = (char **)arg;
  *(*s)++ = c;
}

int xsprintf(char *buf, const char *fmt, va_list args) {
  int res;

  res = (int)McuXFormat_xvformat(putCharIntoBuf, (void *)&buf, fmt, args);
  *buf = 0;
  return res;
}
#endif

/*
 * Lint want declare list as const but list is an obscured pointer so
 * the warning is disabled.
 */
/*lint -save -e818 */


/**
 * Printf like format function.
 *
 * General format :
 *
 * %[width][.precision][flags]type
 *
 * - width Is the minimum size of the field.
 *
 * - precision Is the maximum size of the field.
 *
 * Supported flags :
 *
 * - l  With integer number the argument will be of type long.
 * - ll With integer number the argument will be of type long long.
 * -  Space for positive integer a space will be added before.
 * - z  Compatible with C99 the argument is size_t (aka sizeof(void *))
 * - +  A + sign prefix positive number.
 * - #  A prefix will be printed (o for octal,0x for hex,0b for binary)
 * - 0  Value will be padded with zero (default is spacwe)
 * - -  Left justify as default filed have rigth justification.
 *
 * Supported type :
 *
 * - s  Null terminated string of char.
 * - S  Null terminated string of char in upper case.
 * - i  Integer number.
 * - d  Integer number.
 * - u  Unsigned number.
 * - x  Unsigned number in hex.
 * - X  Unsigned number in hex upper case.
 * - b  Binary number
 * - o  Octal number
 * - p  Pointer will be emitted with the prefix ->
 * - P  Pointer in upper case letter.
 * - f  Floating point number.
 * - B  Boolean value printed as True / False.
 *
 * @param outchar - Pointer to the function to output one char.
 * @param arg - Argument for the output function.
 * @param fmt - Format options for the list of parameters.
 * @param args  - List parameters.
 *
 * @return The number of char emitted.
 */
unsigned McuXFormat_xvformat(void (*outchar)(void *,char), void *arg, const char * fmt, va_list _args)
{
  XCFG_FORMAT_STATIC struct param_s param;
  int i;
  char c;

#if XCFG_FORMAT_VA_COPY
  va_list args;

  va_copy(args,_args);
#else
#define args  _args
#endif

  param.count = 0;
  param.state = ST_NORMAL;

  while (*fmt)
  {
    c = *fmt++;

    if (c < ' ' || c > 'z')
      i = (int)CH_OTHER;
    else
      i = formatStates[c - ' '] & 0x0F;

    param.state = (char)(formatStates[(i << 3) + param.state] >> 4);

    switch (param.state)
    {
      default:
      case  ST_NORMAL:
        (*outchar)(arg,c);
        param.count++;
        break;

      case  ST_PERCENT:
        param.flags = (unsigned)(param.length = param.prefixlen = param.width = param.prec = 0);
        param.pad = ' ';
        break;

      case  ST_WIDTH:
        if (c == '*') {
          param.width = (int)va_arg(args,int);
        } else {
          param.width = param.width * 10 + (c - '0');
        }
        break;

      case  ST_DOT:
        break;

      case  ST_PRECIS:
        param.flags |= FLAG_PREC;
        if (c == '*') {
          param.prec = (int)va_arg(args,int);
        } else {
          param.prec = param.prec * 10 + (c - '0');
        }
        break;

      case  ST_SIZE:
        switch (c)
        {
          default:
            break;
          case 'z':
            param.flags &= ~FLAG_TYPE_MASK;
            param.flags |= FLAG_TYPE_SIZEOF;
            break;

          case 'l':
#if XCFG_FORMAT_LONGLONG
            if ((param.flags & FLAG_TYPE_MASK) == FLAG_TYPE_LONG)
            {
              param.flags &= ~FLAG_TYPE_MASK;
              param.flags |=  FLAG_TYPE_LONGLONG;
            }
            else
            {
              param.flags &= ~FLAG_TYPE_MASK;
              param.flags |= FLAG_TYPE_LONG;

            }
#else
            param.flags &= ~FLAG_TYPE_MASK;
            param.flags |= FLAG_TYPE_LONG;
#endif
            break;


        }
        break;

      case  ST_FLAG:
        switch (c)
        {
          default:
            break;
          case  '-':
            param.flags |= FLAG_LEFT;
            break;
          case  '0':
            param.pad = '0';
            break;
          case ' ':
            param.flags |= FLAG_BLANK;
            break;
          case '#':
            param.flags |= FLAG_PREFIX;
            break;
          case '+':
            param.flags |= FLAG_PLUS;
            break;
        }
        break;

      case  ST_TYPE:
        switch (c)
        {
          default:
            param.length = 0;
            break;

            /*
             * Pointer upper case
             */
          case  'P':
            param.flags |=  FLAG_UPPER;
            /* fall through */
            /*lint -fallthrough */

            /*
             * Pointer
             */
            /* no break */
          case  'p':
            param.flags &= ~FLAG_TYPE_MASK;
            param.flags |= FLAG_INTEGER | FLAG_TYPE_SIZEOF;
            param.radix = 16;
            param.prec = sizeof(void *) * 2;
            param.prefix[0] = '-';
            param.prefix[1] = '>';
            param.prefixlen = 2;
            break;

            /*
             * Binary number
             */
          case  'b':
            param.flags |= FLAG_INTEGER;
            param.radix = 2;
            if (param.flags & FLAG_PREFIX)
            {
              param.prefix[0] = '0';
              param.prefix[1] = 'b';
              param.prefixlen = 2;
            }
            break;

            /*
             * Octal number
             */
          case  'o':
            param.flags |= FLAG_INTEGER;
            param.radix = 8;
            if (param.flags & FLAG_PREFIX)
            {
              param.prefix[0] = '0';
              param.prefixlen = 1;
            }
            break;

            /*
             * Hex number upper case letter.
             */
          case  'X':
            param.flags |= FLAG_UPPER;
            /* fall through */
            /* lint -fallthrough */

            /*
             * Hex number lower case
             */
            /* no break */
          case  'x':
            param.flags |= FLAG_INTEGER;
            param.radix = 16;
            if (param.flags & FLAG_PREFIX)
            {
              param.prefix[0] = '0';
              param.prefix[1] = 'x';
              param.prefixlen = 2;
            }
            break;

            /*
             * Integer number radix 10
             */
          case  'd':
          case  'i':
            param.flags |= FLAG_DECIMAL|FLAG_INTEGER;
            param.radix = 10;
            break;

            /*
             * Unsigned number
             */
          case  'u':
            param.flags |= FLAG_INTEGER;
            param.radix = 10;
            break;

            /*
             * Upper case string
             */
          case  'S':
            param.flags |= FLAG_UPPER;
            /* fall through */
            /*lint -fallthrough */

            /*
             * Normal string
             */
            /* no break */
          case  's':
            param.out = va_arg(args,char *);
            if (param.out == 0)
              param.out = (char *)ms_null;
            param.length = (int)xstrlen(param.out);
            break;

          case 'n': /* write number of characters to the argument pointer location */
            param.out = (char*)va_arg(args,int *);
            if (param.out != 0) {
              *(int*)param.out = param.count;
            }
            break;

            /*
             * Upper case char
             */
          case  'C':
            param.flags |= FLAG_UPPER;
            /* fall through */
            /* lint -fallthrough */

            /*
             * Char
             */
            /* no break */
          case  'c':
            param.out = param.buffer;
            param.buffer[0] = (char)va_arg(args,int);
            param.length = 1;
            break;

#if XCFG_FORMAT_FLOAT
            /**
             * Floating point number
             */
          case 'f':
            if (!(param.flags & FLAG_PREC))
            {
              param.prec = 6;
            }

            param.dbl = va_arg(args,DOUBLE);
            param.values.dvalue = 0.50;
            for (i = 0 ; i < param.prec ; i++)
              param.values.dvalue /= 10.0;

            if (param.dbl < 0)
            {
              param.flags |= FLAG_MINUS;
              param.dbl   -= param.values.dvalue;
              param.iPart    = (FLOAT_LONG)param.dbl;
              param.dbl   -=  (FLOAT_LONG)param.iPart;
              param.dbl    = - param.dbl;
            }
            else
            {
              param.dbl += param.values.dvalue;
              param.iPart = (FLOAT_LONG)param.dbl;
              param.dbl -= param.iPart;
            }


            for (i = 0 ;i < param.prec  ;i++)
              param.dbl *= 10.0;

            param.values.lvalue = (unsigned LONG)param.dbl;

            param.out = param.buffer + sizeof(param.buffer) - 1;
            param.radix = 10;
            if (param.prec)
            {
              ulong2a(&param);
              *param.out -- = '.';
              param.length ++;
            }
            param.flags |= FLAG_INTEGER | FLAG_BUFFER |
                     FLAG_DECIMAL | FLAG_VALUE  | FLOAT_TYPE;

            param.prec = 0;
            param.values.FLOAT_VALUE  = (unsigned FLOAT_LONG)param.iPart;
            break;
#endif

            /**
             * Boolean value
             */
          case 'B':
            if (va_arg(args,int) != 0)
              param.out = (char*)ms_true;
            else
              param.out = (char*)ms_false;

            param.length = (int)xstrlen(param.out);
            break;


        }

        /*
         * Process integer number
         */
        if (param.flags & FLAG_INTEGER)
        {
          if (param.prec == 0)
            param.prec = 1;

          if (!(param.flags & FLAG_VALUE))
          {
            switch (param.flags & FLAG_TYPE_MASK)
            {
              case FLAG_TYPE_SIZEOF:
                param.values.lvalue = (unsigned LONG)va_arg(args,void *);
                break;
              case FLAG_TYPE_LONG:
                if (param.flags & FLAG_DECIMAL) {
                  param.values.lvalue = (unsigned LONG)va_arg(args,long);
                } else {
                  param.values.lvalue = (unsigned LONG)va_arg(args,unsigned long);
                }
                break;

              case FLAG_TYPE_INT:
                if (param.flags & FLAG_DECIMAL) {
                  param.values.lvalue = (unsigned LONG)va_arg(args,int);
                } else {
                  param.values.lvalue = (unsigned LONG)va_arg(args,unsigned int);
                }
                break;
#if XCFG_FORMAT_LONGLONG
              case FLAG_TYPE_LONGLONG:
                param.values.llvalue = (LONGLONG)va_arg(args,long long);
                break;
#endif
              default:
                break;
            }

          }

          if ((param.flags & FLAG_PREFIX) && param.values.lvalue == 0)
          {
            param.prefixlen = 0;
          }


          /*
           * Manage signed integer
           */
          if (param.flags & FLAG_DECIMAL)
          {
#if XCFG_FORMAT_LONGLONG
            if ((param.flags & FLAG_TYPE_MASK) == FLAG_TYPE_LONGLONG)
            {
              if ((LONGLONG)param.values.llvalue < 0)
              {
                param.values.llvalue = ~param.values.llvalue + 1;
                param.flags |= FLAG_MINUS;
              }
            }
            else
            {
#endif
              if ((LONG)param.values.lvalue < 0)
              {
                param.values.lvalue = ~param.values.lvalue + 1;
                param.flags |= FLAG_MINUS;

              }
#if XCFG_FORMAT_LONGLONG
            }
#endif
            if (!(param.flags & FLAG_MINUS)  && (param.flags & FLAG_BLANK))
            {
              param.prefix[0] = ' ';
              param.prefixlen = 1;
            }
          }

          if ((param.flags & FLAG_BUFFER) == 0)
          {
            param.out = param.buffer + sizeof(param.buffer) - 1;
          }


#if XCFG_FORMAT_LONGLONG
          if ((param.flags & FLAG_TYPE_MASK) == FLAG_TYPE_LONGLONG)
            ullong2a(&param);
          else
            ulong2a(&param);
#else

          ulong2a(&param);
#endif
          param.out++;

          /*
           * Check if a sign is required
           */
          if (param.flags & (FLAG_MINUS|FLAG_PLUS))
          {
            c = param.flags & FLAG_MINUS ? '-' : '+';

            if (param.pad == '0')
            {
              param.prefixlen = 1;
              param.prefix[0] = c;
            }
            else
            {
              *--param.out = c;
              param.length++;
            }
          }


        }
        else
        {
          if (param.width && param.length > param.width)
          {
            param.length = param.width;
          }

        }

        /*
         * Now width contain the size of the pad
         */
        param.width -= (param.length + param.prefixlen);

        param.count += outBuffer(outchar,arg,param.prefix,param.prefixlen,param.flags & FLAG_UPPER);
        if (!(param.flags & FLAG_LEFT))
          param.count += outChars(outchar,arg,param.pad,param.width);
        param.count += outBuffer(outchar,arg,param.out,param.length,param.flags & FLAG_UPPER);
        if (param.flags & FLAG_LEFT)
          param.count += outChars(outchar,arg,param.pad,param.width);

    }
  }

#if XCFG_FORMAT_VA_COPY
  va_end(args);
#endif

  return param.count;
}
/*lint -restore */

/*
** ===================================================================
**     Method      :  xsprintf (component XFormat)
**
**     Description :
**         sprintf() like function
**     Parameters  :
**         NAME            - DESCRIPTION
**       * buf             - Pointer to buffer to be written
**       * fmt             - Pointer to formatting string
**         argList         - Open Argument List
**     Returns     :
**         ---             - number of characters written, negative for
**                           error case
** ===================================================================
*/
int McuXFormat_xsprintf(char *buf, const char *fmt, ...)
{
  va_list args;
  int res;

  va_start(args,fmt);
  res = xsprintf(buf, fmt, args);
  va_end(args);
  return res;
}


/*
** ===================================================================
**     Method      :  xsnprintf (component XFormat)
**
**     Description :
**         snprintf() like function, returns the number of characters
**         written, negative in case of error.
**     Parameters  :
**         NAME            - DESCRIPTION
**       * buf             - Pointer to buffer to be written
**         max_len         - size of output buffer (in size)
**       * fmt             - Pointer to formatting string
**         argList         - Open Argument List
**     Returns     :
**         ---             - number of characters written, negative for
**                           error case
** ===================================================================
*/
int McuXFormat_xsnprintf(char *buf, size_t max_len, const char *fmt, ...)
{
  va_list args;
  int res;

  va_start(args,fmt);
  res = xsnprintf(buf, max_len, fmt, args);
  va_end(args);
  return res;
}

/*
** ===================================================================
**     Method      :  Init (component XFormat)
**
**     Description :
**         Driver initialization routine
**     Parameters  : None
**     Returns     : Nothing
** ===================================================================
*/
void McuXFormat_Init(void)
{
  /* nothing needed */
}

/*
** ===================================================================
**     Method      :  Deinit (component XFormat)
**
**     Description :
**         Driver de-initialization routine
**     Parameters  : None
**     Returns     : Nothing
** ===================================================================
*/
void McuXFormat_Deinit(void)
{
  /* nothing needed */
}

/* END McuXFormat. */

/*!
** @}
*/
