1217 lines
30 KiB
C
1217 lines
30 KiB
C
/* ###################################################################
|
|
** 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(¶m);
|
|
*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(¶m);
|
|
else
|
|
ulong2a(¶m);
|
|
#else
|
|
|
|
ulong2a(¶m);
|
|
#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. */
|
|
|
|
/*!
|
|
** @}
|
|
*/
|