OpenModem/bertos/mware/formatwr.c

979 lines
22 KiB
C

/**
* \file
* <!--
* This file is part of BeRTOS.
*
* Bertos is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*
* Copyright 2003, 2004, 2005, 2008 Develer S.r.l. (http://www.develer.com/)
*
* -->
*
*
* \brief Basic "printf", "sprintf" and "fprintf" formatter.
*
* This module is 100% reentrant and can be adapted to user-defined routines
* that needs formatters with special properties like different output
* channels or new format specifiers.
*
* To reduce size in applications not using real numbers or long integers
* the formatter may be compiled to exclude certain parts. This is
* controlled by giving a -D option a compilation time:
*
* \code
* -D CONFIG_PRINTF=PRINTF_FULL Full ANSI printf formatter, with some C99 extensions
* -D CONFIG_PRINTF=PRINTF_NOFLOAT Exclude support for floats
* -D CONFIG_PRINTF=PRINTF_REDUCED Simplified formatter (see below)
* -D CONFIG_PRINTF=PRINTF_NOMODIFIERS Exclude "l", "z" and "h" modifiers in reduced version
* -D CONFIG_PRINTF=PRINTF_DISABLED No formatter at all
* \endcode
*
* Code size on AVR4 with GCC 3.4.1 (-O2):
* \li PRINTF_FULL 2912byte (0xB60)
* \li PRINTF_NOFLOAT 1684byte (0x694)
* \li PRINTF_REDUCED 924byte (0x39C)
* \li PRINTF_NOMODIFIERS 416byte (0x1A0)
*
* Code/data size in words on DSP56K with CodeWarrior 6.0:
* \li PRINTF_FULL 1493/45
* \li PRINTF_NOFLOAT 795/45
* \li PRINTF_REDUCED 482/0
* \li PRINTF_NOMODIFIERS 301/0
*
* The reduced version of formatter is suitable when program size is critical
* rather than formatting power. This routine uses less than 20 bytes of
* stack space which makes it practical even in systems with less than 256
* bytes of user RAM.
*
* The only formatting specifiers supported by the reduced formatter are:
* \code
* %% %c %s %d %o %x %X and %hd %ho %hx %hX %ld %lo %lx %lX
* \endcode
*
* It means that real variables are not supported as well as field
* width and precision arguments.
*/
#include "formatwr.h"
#include "cfg/cfg_formatwr.h" /* CONFIG_ macros */
#include <cfg/debug.h> /* ASSERT */
#include <cpu/pgm.h>
#include <mware/hex.h>
#ifndef CONFIG_PRINTF_N_FORMATTER
/** Disable the arcane %n formatter. */
#define CONFIG_PRINTF_N_FORMATTER 0
#endif
#ifndef CONFIG_PRINTF_OCTAL_FORMATTER
/** Disable the %o formatter. */
#define CONFIG_PRINTF_OCTAL_FORMATTER 0
#endif
/* True if we must keep a count of the number of characters we print. */
#define CONFIG_PRINTF_COUNT_CHARS (CONFIG_PRINTF_RETURN_COUNT || CONFIG_PRINTF_N_FORMATTER)
#if CONFIG_PRINTF
#if CONFIG_PRINTF > PRINTF_NOFLOAT
#include <float.h>
/* Maximum precision for floating point values */
typedef long double max_float_t;
#if CONFIG_FRMWRI_BUFSIZE
#define FRMWRI_BUFSIZE CONFIG_FRMWRI_BUFSIZE
#else
/* Conservative estimate. Max float is 3.40282e+038, so %f (but not %e or %g) must have
* space for: sign + all 38 digits + '.' + 6 decimal digits (default)
* Use a high value to avoid unexpected buffer overflows.
*/
#define FRMWRI_BUFSIZE 134
#endif
#else
#if CONFIG_FRMWRI_BUFSIZE
#define FRMWRI_BUFSIZE CONFIG_FRMWRI_BUFSIZE
#else
/*
* Conservative estimate. Should be (probably) 12 (which is the size necessary
* to represent (2^32-1) in octal plus the sign bit.
*/
#define FRMWRI_BUFSIZE 16
#endif
#endif
/* Probably useful for fancy microcontrollers such as the PIC, nobody knows. */
#ifndef MEM_ATTRIBUTE
#define MEM_ATTRIBUTE
#endif
#if CONFIG_PRINTF > PRINTF_NOMODIFIERS
#define IS_SHORT (h_modifier || (sizeof(int) == 2 && !l_modifier))
#else
#define IS_SHORT (sizeof(int) == 2)
#endif /* CONFIG_PRINTF > PRINTF_NOMODIFIERS */
#if CONFIG_PRINTF > PRINTF_NOFLOAT
static char *float_conversion(MEM_ATTRIBUTE max_float_t value,
MEM_ATTRIBUTE short nr_of_digits,
MEM_ATTRIBUTE char *buf,
MEM_ATTRIBUTE char format_flag,
MEM_ATTRIBUTE char g_flag,
MEM_ATTRIBUTE bool alternate_flag)
{
MEM_ATTRIBUTE char *cp;
MEM_ATTRIBUTE char *buf_pointer;
MEM_ATTRIBUTE short n, i, dec_point_pos, integral_10_log;
buf_pointer = buf;
integral_10_log = 0;
if (value >= 1)
{
while (value >= 1e11) /* To speed up things a bit */
{
value /= 1e10;
integral_10_log += 10;
}
while (value >= 10)
{
value /= 10;
integral_10_log++;
}
}
else if (value) /* Not just 0.0 */
{
while (value <= 1e-10) /* To speed up things a bit */
{
value *= 1e10;
integral_10_log -= 10;
}
while (value < 1)
{
value *= 10;
integral_10_log--;
}
}
if (g_flag)
{
if (integral_10_log < nr_of_digits && integral_10_log >= -4)
{
format_flag = 0;
nr_of_digits -= integral_10_log;
}
nr_of_digits--;
if (alternate_flag)
/* %#G - No removal of trailing zeros */
g_flag = 0;
else
/* %G - Removal of trailing zeros */
alternate_flag = true;
}
/* %e or %E */
if (format_flag)
{
dec_point_pos = 0;
}
else
{
/* Less than one... */
if (integral_10_log < 0)
{
*buf_pointer++ = '0';
if ((n = nr_of_digits) || alternate_flag)
*buf_pointer++ = '.';
i = 0;
while (--i > integral_10_log && nr_of_digits)
{
*buf_pointer++ = '0';
nr_of_digits--;
}
if (integral_10_log < (-n - 1))
/* Nothing more to do */
goto CLEAN_UP;
dec_point_pos = 1;
}
else
{
dec_point_pos = - integral_10_log;
}
}
i = dec_point_pos;
while (i <= nr_of_digits )
{
value -= (max_float_t)(n = (short)value); /* n=Digit value=Remainder */
value *= 10; /* Prepare for next shot */
*buf_pointer++ = n + '0';
if ( ! i++ && (nr_of_digits || alternate_flag))
*buf_pointer++ = '.';
}
/* Rounding possible */
if (value >= 5)
{
n = 1; /* Carry */
cp = buf_pointer - 1;
do
{
if (*cp != '.')
{
if ( (*cp += n) == ('9' + 1) )
{
*cp = '0';
n = 1;
}
else
n = 0;
}
} while (cp-- > buf);
if (n)
{
/* %e or %E */
if (format_flag)
{
cp = buf_pointer;
while (cp > buf)
{
if (*(cp - 1) == '.')
{
*cp = *(cp - 2);
cp--;
}
else
*cp = *(cp - 1);
cp--;
}
integral_10_log++;
}
else
{
cp = ++buf_pointer;
while (cp > buf)
{
*cp = *(cp - 1);
cp--;
}
}
*buf = '1';
}
}
CLEAN_UP:
/* %G - Remove trailing zeros */
if (g_flag)
{
while (*(buf_pointer - 1) == '0')
buf_pointer--;
if (*(buf_pointer - 1) == '.')
buf_pointer--;
}
/* %e or %E */
if (format_flag)
{
*buf_pointer++ = format_flag;
if (integral_10_log < 0)
{
*buf_pointer++ = '-';
integral_10_log = -integral_10_log;
}
else
*buf_pointer++ = '+';
n = 0;
buf_pointer +=10;
do
{
n++;
*buf_pointer++ = (integral_10_log % 10) + '0';
integral_10_log /= 10;
} while ( integral_10_log || n < 2 );
for ( i = n ; n > 0 ; n-- )
*(buf_pointer - 11 - i + n) = *(buf_pointer - n);
buf_pointer -= 10;
}
return (buf_pointer);
}
#endif /* CONFIG_PRINTF > PRINTF_NOFLOAT */
/**
* This routine forms the core and entry of the formatter.
*
* The conversion performed conforms to the ANSI specification for "printf".
*/
int
PGM_FUNC(_formatted_write)(const char * PGM_ATTR format,
void put_one_char(char, void *),
void *secret_pointer,
va_list ap)
{
#if CONFIG_PRINTF > PRINTF_REDUCED
MEM_ATTRIBUTE static char bad_conversion[] = "???";
MEM_ATTRIBUTE static char null_pointer[] = "<NULL>";
MEM_ATTRIBUTE int precision;
MEM_ATTRIBUTE int n;
#if CONFIG_PRINTF_COUNT_CHARS
MEM_ATTRIBUTE int nr_of_chars;
#endif
MEM_ATTRIBUTE int field_width;
MEM_ATTRIBUTE char format_flag;
enum PLUS_SPACE_FLAGS {
PSF_NONE, PSF_PLUS, PSF_MINUS
};
enum DIV_FACTOR {
DIV_DEC, DIV_HEX,
#if CONFIG_PRINTF_OCTAL_FORMATTER
DIV_OCT,
#endif
};
MEM_ATTRIBUTE struct {
enum PLUS_SPACE_FLAGS plus_space_flag : 2;
#if CONFIG_PRINTF_OCTAL_FORMATTER
enum DIV_FACTOR div_factor : 2;
#else
enum DIV_FACTOR div_factor : 1;
#endif
bool left_adjust : 1;
bool l_L_modifier : 1;
bool h_modifier : 1;
bool alternate_flag : 1;
bool nonzero_value : 1;
bool zeropad : 1;
#if CPU_HARVARD
bool progmem : 1;
#endif
} flags;
MEM_ATTRIBUTE unsigned long ulong;
#if CONFIG_PRINTF > PRINTF_NOFLOAT
MEM_ATTRIBUTE max_float_t fvalue;
#endif
MEM_ATTRIBUTE char *buf_pointer;
MEM_ATTRIBUTE char *ptr;
MEM_ATTRIBUTE const char *hex;
MEM_ATTRIBUTE char buf[FRMWRI_BUFSIZE];
#if CONFIG_PRINTF_COUNT_CHARS
nr_of_chars = 0;
#endif
for (;;) /* Until full format string read */
{
while ((format_flag = PGM_READ_CHAR(format++)) != '%') /* Until '%' or '\0' */
{
if (!format_flag)
#if CONFIG_PRINTF_RETURN_COUNT
return (nr_of_chars);
#else
return 0;
#endif
put_one_char(format_flag, secret_pointer);
#if CONFIG_PRINTF_COUNT_CHARS
nr_of_chars++;
#endif
}
if (PGM_READ_CHAR(format) == '%') /* %% prints as % */
{
format++;
put_one_char('%', secret_pointer);
#if CONFIG_PRINTF_COUNT_CHARS
nr_of_chars++;
#endif
continue;
}
flags.left_adjust = false;
flags.alternate_flag = false;
flags.plus_space_flag = PSF_NONE;
flags.zeropad = false;
#if CPU_HARVARD
flags.progmem = false;
#endif
ptr = buf_pointer = &buf[0];
hex = HEX_tab;
/* check for leading '-', '+', ' ','#' or '0' flags */
for (;;)
{
switch (PGM_READ_CHAR(format))
{
case ' ':
if (flags.plus_space_flag)
goto NEXT_FLAG;
case '+':
flags.plus_space_flag = PSF_PLUS;
goto NEXT_FLAG;
case '-':
flags.left_adjust = true;
goto NEXT_FLAG;
case '#':
flags.alternate_flag = true;
goto NEXT_FLAG;
case '0':
flags.zeropad = true;
goto NEXT_FLAG;
}
break;
NEXT_FLAG:
format++;
}
/* Optional field width (may be '*') */
if (PGM_READ_CHAR(format) == '*')
{
field_width = va_arg(ap, int);
if (field_width < 0)
{
field_width = -field_width;
flags.left_adjust = true;
}
format++;
}
else
{
field_width = 0;
while (PGM_READ_CHAR(format) >= '0' && PGM_READ_CHAR(format) <= '9')
field_width = field_width * 10 + (PGM_READ_CHAR(format++) - '0');
}
if (flags.left_adjust)
flags.zeropad = false;
/* Optional precision (or '*') */
if (PGM_READ_CHAR(format) == '.')
{
if (PGM_READ_CHAR(++format) == '*')
{
precision = va_arg(ap, int);
format++;
}
else
{
precision = 0;
while (PGM_READ_CHAR(format) >= '0' && PGM_READ_CHAR(format) <= '9')
precision = precision * 10 + (PGM_READ_CHAR(format++) - '0');
}
}
else
precision = -1;
/* At this point, "left_adjust" is nonzero if there was
* a sign, "zeropad" is 1 if there was a leading zero
* and 0 otherwise, "field_width" and "precision"
* contain numbers corresponding to the digit strings
* before and after the decimal point, respectively,
* and "plus_space_flag" is either 0 (no flag) or
* contains a plus or space character. If there was no
* decimal point, "precision" will be -1.
*/
flags.l_L_modifier = false;
flags.h_modifier = false;
/* Optional 'l','L','z' or 'h' modifier? */
switch (PGM_READ_CHAR(format))
{
case 'l':
case 'L':
#if SIZEOF_SIZE_T == SIZEOF_LONG
case 'z':
flags.l_L_modifier = true;
#elif SIZEOF_SIZE_T == SIZEOF_INT
flags.l_L_modifier = true;
case 'z':
#endif
format++;
break;
case 'h':
flags.h_modifier = true;
format++;
break;
}
/*
* At exit from the following switch, we will emit
* the characters starting at "buf_pointer" and
* ending at "ptr"-1
*/
switch (format_flag = PGM_READ_CHAR(format++))
{
#if CONFIG_PRINTF_N_FORMATTER
case 'n':
if (sizeof(short) != sizeof(int))
{
if (sizeof(int) != sizeof(long))
{
if (h_modifier)
*va_arg(ap, short *) = nr_of_chars;
else if (flags.l_L_modifier)
*va_arg(ap, long *) = nr_of_chars;
else
*va_arg(ap, int *) = nr_of_chars;
}
else
{
if (h_modifier)
*va_arg(ap, short *) = nr_of_chars;
else
*va_arg(ap, int *) = nr_of_chars;
}
}
else
{
if (flags.l_L_modifier)
*va_arg(ap, long *) = nr_of_chars;
else
*va_arg(ap, int *) = nr_of_chars;
}
continue;
#endif
case 'c':
buf[0] = va_arg(ap, int);
ptr++;
break;
/* Custom formatter for strings in program memory. */
case 'S':
#if CPU_HARVARD
flags.progmem = true;
#endif
/* Fall trough */
case 's':
if ( !(buf_pointer = va_arg(ap, char *)) )
buf_pointer = null_pointer;
if (precision < 0)
precision = 10000;
/*
* Move `ptr' to the last character of the
* string that will be actually printed.
*/
ptr = buf_pointer;
#if CPU_HARVARD
if (flags.progmem)
{
for (n=0; pgm_read_char(ptr) && n < precision; n++)
++ptr;
}
else
#endif
for (n=0; *ptr && n < precision; n++)
++ptr;
break;
#if CONFIG_PRINTF_OCTAL_FORMATTER
case 'o':
if (flags.alternate_flag && !precision)
precision++;
#endif
case 'x':
hex = hex_tab;
case 'u':
case 'p':
case 'X':
if (format_flag == 'p')
#if defined(__AVR__) || defined(__I196__) || defined(__MSP430__) /* 16bit pointers */
ulong = (unsigned long)(unsigned short)va_arg(ap, char *);
#else /* 32bit pointers */
ulong = (unsigned long)va_arg(ap, char *);
#endif /* 32bit pointers */
else if (flags.l_L_modifier)
ulong = va_arg(ap, unsigned long);
else if (flags.h_modifier)
ulong = (unsigned long)(unsigned short)va_arg(ap, unsigned int);
else
ulong = va_arg(ap, unsigned int);
flags.div_factor =
#if CONFIG_PRINTF_OCTAL_FORMATTER
(format_flag == 'o') ? DIV_OCT :
#endif
(format_flag == 'u') ? DIV_DEC : DIV_HEX;
flags.plus_space_flag = PSF_NONE;
goto INTEGRAL_CONVERSION;
case 'd':
case 'i':
if (flags.l_L_modifier)
ulong = (unsigned long)(long)va_arg(ap, long);
else
ulong = (unsigned long)(long)va_arg(ap, int);
/* Extract sign */
if ((signed long)ulong < 0)
{
flags.plus_space_flag = PSF_MINUS;
ulong = (unsigned long)(-((signed long)ulong));
}
flags.div_factor = DIV_DEC;
/* Now convert to digits */
INTEGRAL_CONVERSION:
ptr = buf_pointer = &buf[FRMWRI_BUFSIZE - 1];
flags.nonzero_value = (ulong != 0);
/* No char if zero and zero precision */
if (precision != 0 || flags.nonzero_value)
{
switch (flags.div_factor)
{
case DIV_DEC:
do
*--buf_pointer = hex[ulong % 10];
while (ulong /= 10);
break;
case DIV_HEX:
do
*--buf_pointer = hex[ulong % 16];
while (ulong /= 16);
break;
#if CONFIG_PRINTF_OCTAL_FORMATTER
case DIV_OCT:
do
*--buf_pointer = hex[ulong % 8];
while (ulong /= 8);
break;
#endif
}
}
/* "precision" takes precedence */
if (precision < 0)
if (flags.zeropad)
precision = field_width - (flags.plus_space_flag != PSF_NONE);
while (precision > (int)(ptr - buf_pointer))
*--buf_pointer = '0';
if (flags.alternate_flag && flags.nonzero_value)
{
if (format_flag == 'x' || format_flag == 'X')
{
*--buf_pointer = format_flag;
*--buf_pointer = '0';
}
#if CONFIG_PRINTF_OCTAL_FORMATTER
else if ((format_flag == 'o') && (*buf_pointer != '0'))
{
*--buf_pointer = '0';
}
#endif
}
ASSERT(buf_pointer >= buf);
break;
#if CONFIG_PRINTF > PRINTF_NOFLOAT
case 'g':
case 'G':
n = 1;
format_flag -= 2;
if (! precision)
{
precision = 1;
}
goto FLOATING_CONVERSION;
case 'f':
format_flag = 0;
case 'e':
case 'E':
n = 0;
FLOATING_CONVERSION:
if (precision < 0)
{
precision = 6;
}
if (sizeof(double) != sizeof(max_float_t))
{
fvalue = flags.l_L_modifier ?
va_arg(ap,max_float_t) : va_arg(ap,double);
}
else
fvalue = va_arg(ap,max_float_t);
if (fvalue < 0)
{
flags.plus_space_flag = PSF_MINUS;
fvalue = -fvalue;
}
ptr = float_conversion (fvalue,
(short)precision,
buf_pointer += field_width,
format_flag,
(char)n,
flags.alternate_flag);
if (flags.zeropad)
{
precision = field_width - (flags.plus_space_flag != PSF_NONE);
while (precision > ptr - buf_pointer)
*--buf_pointer = '0';
}
break;
#endif /* CONFIG_PRINTF <= PRINTF_NOFLOAT */
case '\0': /* Really bad place to find NUL in */
format--;
default:
/* Undefined conversion! */
ptr = buf_pointer = bad_conversion;
ptr += sizeof(bad_conversion) - 1;
break;
}
/*
* This part emittes the formatted string to "put_one_char".
*/
/* If field_width == 0 then nothing should be written. */
precision = ptr - buf_pointer;
if ( precision > field_width)
{
n = 0;
}
else
{
n = field_width - precision - (flags.plus_space_flag != PSF_NONE);
}
/* emit any leading pad characters */
if (!flags.left_adjust)
while (--n >= 0)
{
put_one_char(' ', secret_pointer);
#if CONFIG_PRINTF_COUNT_CHARS
nr_of_chars++;
#endif
}
/* emit flag characters (if any) */
if (flags.plus_space_flag)
{
put_one_char(flags.plus_space_flag == PSF_PLUS ? '+' : '-', secret_pointer);
#if CONFIG_PRINTF_COUNT_CHARS
nr_of_chars++;
#endif
}
#if CPU_HARVARD
if (flags.progmem)
{
while (--precision >= 0)
{
put_one_char(pgm_read_char(buf_pointer++), secret_pointer);
#if CONFIG_PRINTF_COUNT_CHARS
nr_of_chars++;
#endif
}
}
else
#endif /* CPU_HARVARD */
{
/* emit the string itself */
while (--precision >= 0)
{
put_one_char(*buf_pointer++, secret_pointer);
#if CONFIG_PRINTF_COUNT_CHARS
nr_of_chars++;
#endif
}
}
/* emit trailing space characters */
if (flags.left_adjust)
while (--n >= 0)
{
put_one_char(' ', secret_pointer);
#if CONFIG_PRINTF_COUNT_CHARS
nr_of_chars++;
#endif
}
}
#else /* PRINTF_REDUCED starts here */
#if CONFIG_PRINTF > PRINTF_NOMODIFIERS
bool l_modifier, h_modifier;
unsigned long u_val, div_val;
#else
unsigned int u_val, div_val;
#endif /* CONFIG_PRINTF > PRINTF_NOMODIFIERS */
char format_flag;
unsigned int nr_of_chars, base;
char outChar;
char *ptr;
nr_of_chars = 0;
for (;;) /* Until full format string read */
{
while ((format_flag = PGM_READ_CHAR(format++)) != '%') /* Until '%' or '\0' */
{
if (!format_flag)
return (nr_of_chars);
put_one_char(format_flag, secret_pointer);
nr_of_chars++;
}
#if CONFIG_PRINTF > PRINTF_NOMODIFIERS
/*
* Optional 'l', 'z' or 'h' modifiers?
*/
l_modifier = h_modifier = false;
switch (PGM_READ_CHAR(format))
{
case 'l':
#if SIZEOF_SIZE_T == SIZEOF_LONG
case 'z':
l_modifier = true;
#elif SIZEOF_SIZE_T == SIZEOF_INT
l_modifier = true;
case 'z':
#endif
format++;
break;
case 'h':
h_modifier = true;
format++;
break;
}
#endif /* CONFIG_PRINTF > PRINTF_NOMODIFIERS */
switch (format_flag = PGM_READ_CHAR(format++))
{
case 'c':
format_flag = va_arg(ap, int);
default:
put_one_char(format_flag, secret_pointer);
nr_of_chars++;
continue;
case 's':
ptr = va_arg(ap, char *);
while ((format_flag = *ptr++))
{
put_one_char(format_flag, secret_pointer);
nr_of_chars++;
}
continue;
case 'o':
base = 8;
if (IS_SHORT)
div_val = 0x8000;
else
div_val = 0x40000000;
goto CONVERSION_LOOP;
case 'd':
base = 10;
if (IS_SHORT)
div_val = 10000;
else
div_val = 1000000000;
goto CONVERSION_LOOP;
case 'X':
case 'x':
base = 16;
if (IS_SHORT)
div_val = 0x1000;
else
div_val = 0x10000000;
CONVERSION_LOOP:
#if CONFIG_PRINTF > PRINTF_NOMODIFIERS
if (h_modifier)
{
if (format_flag == 'd')
u_val = (short)va_arg(ap, int);
else
u_val = (unsigned short)va_arg(ap, int);
}
else if (l_modifier)
u_val = va_arg(ap, long);
else
{
if (format_flag == 'd')
u_val = va_arg(ap, int);
else
u_val = va_arg(ap, unsigned int);
}
#else /* CONFIG_PRINTF > PRINTF_NOMODIFIERS */
u_val = va_arg(ap,int);
#endif /* CONFIG_PRINTF > PRINTF_NOMODIFIERS */
if (format_flag == 'd')
{
if (((int)u_val) < 0)
{
u_val = - u_val;
put_one_char('-', secret_pointer);
nr_of_chars++;
}
}
while (div_val > 1 && div_val > u_val)
{
div_val /= base;
}
do
{
outChar = (u_val / div_val) + '0';
if (outChar > '9')
{
if (format_flag == 'x')
outChar += 'a'-'9'-1;
else
outChar += 'A'-'9'-1;
}
put_one_char(outChar, secret_pointer);
nr_of_chars++;
u_val %= div_val;
div_val /= base;
}
while (div_val);
} /* end switch(format_flag...) */
}
#endif /* CONFIG_PRINTF > PRINTF_REDUCED */
}
#endif /* CONFIG_PRINTF */