Add support for accessing printf, sprintf, puts, etc. strings that do not lie in the MCU data space
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3738 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
7ce352ca5c
commit
e6c8a184b9
@ -1839,5 +1839,13 @@
|
||||
and was, therefore, off by one, and (2) Some devices stall of get Max LUN request
|
||||
if they support only a single LUN. Logic now assumes a single LUN if the get
|
||||
Max LUN request fails.
|
||||
* include/nuttx/arch.h, lib/stdio/lib_libvsprintf.c, lib/stdio/lib_fputs.c: Add
|
||||
a new configuration option to support extracting strings from FLASH or EEPROM
|
||||
or other memories where the string data cannot be accessed by simply de-referencing
|
||||
a string pointer.
|
||||
* arch/sim/src/up_romgetc.c: Used to test the basic logic to access strings
|
||||
without directly de-referencing a string pointer.
|
||||
* arch/avr/src/avr/up_romget.c: Used to access strings that lie in the first
|
||||
64Kb of FLASH.
|
||||
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
<h1><big><font color="#3c34ec">
|
||||
<i>NuttX RTOS Porting Guide</i>
|
||||
</font></big></h1>
|
||||
<p>Last Updated: June 18, 2011</p>
|
||||
<p>Last Updated: July 1, 2011</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@ -3628,34 +3628,65 @@ build
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<code>CONFIG_NOPRINTF_FIELDWIDTH</code>: sprintf-related logic is a
|
||||
<code>CONFIG_NOPRINTF_FIELDWIDTH</code>: <code>sprintf</code>-related logic is a
|
||||
little smaller if we do not support fieldwidthes
|
||||
</li>
|
||||
<li>
|
||||
<code>CONFIG_LIBC_FLOATINGPOINT</code>: By default, floating point
|
||||
support in printf, sscanf, etc. is disabled.
|
||||
support in <code>printf</code>, <code>sscanf</code>, etc. is disabled.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>Allow for architecture optimized implementations</h2>
|
||||
|
||||
<p>
|
||||
The architecture can provide optimized versions of the following to improve system performance.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<p>
|
||||
<li>
|
||||
The architecture can provide optimized versions of the following to improve system performance.
|
||||
</li>
|
||||
<ul><p>
|
||||
<code>CONFIG_ARCH_MEMCPY</code>, <code>CONFIG_ARCH_MEMCMP</code>, <code>CONFIG_ARCH_MEMMOVE</code>,
|
||||
<code>CONFIG_ARCH_MEMSET</code>, <code>CONFIG_ARCH_STRCMP</code>, <code>CONFIG_ARCH_STRCPY</code>,
|
||||
<code>CONFIG_ARCH_STRNCPY</code>, <code>CONFIG_ARCH_STRLEN</code>, <code>CONFIG_ARCH_STRNLEN</code>,
|
||||
<code>CONFIG_ARCH_BZERO</code>
|
||||
</p>
|
||||
<p>
|
||||
</p></ul>
|
||||
|
||||
<li>
|
||||
The architecture may provide custom versions of certain standard header files:
|
||||
</p>
|
||||
<p>
|
||||
</li>
|
||||
<ul><p>
|
||||
<code>CONFIG_ARCH_MATH_H</code>, <code>CONFIG_ARCH_STDBOOL_H</code>, <code>CONFIG_ARCH_STDINT_H</code>
|
||||
</p>
|
||||
</p></ul>
|
||||
|
||||
<li>
|
||||
<p><code>CONFIG_ARCH_ROMGETC</code>:
|
||||
There are cases where string data cannot be cannot be accessed by simply de-referencing a string pointer.
|
||||
As examples:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
In Harvard architectures, data accesses and instruction accesses occur on different busses, perhaps concurrently.
|
||||
All data accesses are performed on the data bus unless special machine instructions are used to read data from the instruction address space.
|
||||
Also, in the typical MCU, the available SRAM data memory is much smaller that the non-volatile FLASH instruction memory.
|
||||
So if the application requires many constant strings, the only practical solution may be to store those constant strings in FLASH memory where they can only be accessed using architecture-specific machine instructions.
|
||||
</li>
|
||||
<li>
|
||||
A similar case is where strings are retained in "external" memory such as EEPROM or serial FLASH.
|
||||
This case is similar only in that again special operations are required to obtain the string data;
|
||||
it cannot be accessed directly from a string pointer.
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
If <code>CONFIG_ARCH_ROMGETC</code> is defined, then the architecture-specific logic must export the function <code>up_romgetc()</code>.
|
||||
<code>up_romgetc()</code> will simply read one byte of data from the instruction space.
|
||||
</p>
|
||||
<p>
|
||||
If <code>CONFIG_ARCH_ROMGETC</code>, certain C stdio functions are effected:
|
||||
(1) All format strings in <code>printf</code>, <code>fprintf</code>, <code>sprintf</code>, etc. are assumed to lie in FLASH
|
||||
(string arguments for <code>%s</code> are still assumed to reside in SRAM).
|
||||
And (2), the string argument to <code>puts</code> and <code>fputs</code> is assumed to reside in FLASH.
|
||||
Clearly, these assumptions may have to modified for the particular needs of your environment.
|
||||
There is no "one-size-fits-all" solution for this problem.
|
||||
</p>
|
||||
</ul>
|
||||
|
||||
<h2>Sizes of configurable things (0 disables)</h2>
|
||||
|
@ -76,11 +76,16 @@ typedef signed long long _int64_t; /* long long is 64-bits */
|
||||
typedef unsigned long long _uint64_t;
|
||||
#define __INT64_DEFINED
|
||||
|
||||
/* A pointer is 2 bytes */
|
||||
/* A (near) pointer is 2 bytes */
|
||||
|
||||
typedef signed int _intptr_t;
|
||||
typedef unsigned int _uintptr_t;
|
||||
|
||||
/* A FAR pointer is 4 bytes */
|
||||
|
||||
typedef signed long _int_farptr_t;
|
||||
typedef unsigned long _uint_farptr_t;
|
||||
|
||||
/* This is the size of the interrupt state save returned by irqsave(). */
|
||||
|
||||
typedef unsigned char irqstate_t;
|
||||
|
@ -62,6 +62,10 @@ ifeq ($(CONFIG_DEBUG_STACK),y)
|
||||
CMN_CSRCS += up_checkstack.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_ROMGETC),y)
|
||||
CMN_CSRCS += up_romgetc.c
|
||||
endif
|
||||
|
||||
# Required AT90USB files
|
||||
|
||||
CHIP_ASRCS = at90usb_exceptions.S
|
||||
|
@ -62,6 +62,10 @@ ifeq ($(CONFIG_DEBUG_STACK),y)
|
||||
CMN_CSRCS += up_checkstack.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_ROMGETC),y)
|
||||
CMN_CSRCS += up_romgetc.c
|
||||
endif
|
||||
|
||||
# Required ATMEGA files
|
||||
|
||||
CHIP_ASRCS = atmega_exceptions.S
|
||||
|
@ -64,9 +64,15 @@ HOSTSRCS = up_stdio.c up_hostusleep.c
|
||||
ifeq ($(USEX),y)
|
||||
HOSTSRCS += up_x11framebuffer.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_FS_FAT),y)
|
||||
CSRCS += up_blockdevice.c up_deviceimage.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_ROMGETC),y)
|
||||
CSRCS += up_romgetc.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NET),y)
|
||||
CSRCS += up_uipdriver.c
|
||||
HOSTCFLAGS += -DNETDEV_BUFSIZE=$(CONFIG_NET_BUFSIZE)
|
||||
|
@ -489,15 +489,39 @@ defconfig -- This is a configuration file similar to the Linux
|
||||
The architecture can provide optimized versions of the
|
||||
following to improve system performance
|
||||
|
||||
CONFIG_ARCH_MEMCPY, CONFIG_ARCH_MEMCMP, CONFIG_ARCH_MEMMOVE
|
||||
CONFIG_ARCH_MEMSET, CONFIG_ARCH_STRCMP, CONFIG_ARCH_STRCPY
|
||||
CONFIG_ARCH_STRNCPY, CONFIG_ARCH_STRLEN, CONFIG_ARCH_STRNLEN
|
||||
CONFIG_ARCH_BZERO
|
||||
CONFIG_ARCH_MEMCPY, CONFIG_ARCH_MEMCMP, CONFIG_ARCH_MEMMOVE
|
||||
CONFIG_ARCH_MEMSET, CONFIG_ARCH_STRCMP, CONFIG_ARCH_STRCPY
|
||||
CONFIG_ARCH_STRNCPY, CONFIG_ARCH_STRLEN, CONFIG_ARCH_STRNLEN
|
||||
CONFIG_ARCH_BZERO
|
||||
|
||||
The architecture may provide custom versions of certain
|
||||
standard header files:
|
||||
|
||||
CONFIG_ARCH_MATH_H, CONFIG_ARCH_STDBOOL_H, CONFIG_ARCH_STDINT_H
|
||||
CONFIG_ARCH_MATH_H, CONFIG_ARCH_STDBOOL_H, CONFIG_ARCH_STDINT_H
|
||||
|
||||
CONFIG_ARCH_ROMGETC - In Harvard architectures, data accesses and
|
||||
instruction accesses occur on different busses, perhaps
|
||||
concurrently. All data accesses are performed on the data bus
|
||||
unless special machine instructions are used to read data
|
||||
from the instruction address space. Also, in the typical
|
||||
MCU, the available SRAM data memory is much smaller that the
|
||||
non-volatile FLASH instruction memory. So if the application
|
||||
requires many constant strings, the only practical solution may
|
||||
be to store those constant strings in FLASH memory where they
|
||||
can only be accessed using architecture-specific machine
|
||||
instructions.
|
||||
|
||||
If CONFIG_ARCH_ROMGETC is defined, then the architecture logic
|
||||
must export the function up_romgetc(). up_romgetc() will simply
|
||||
read one byte of data from the instruction space.
|
||||
|
||||
If CONFIG_ARCH_ROMGETC, certain C stdio functions are effected:
|
||||
(1) All format strings in printf, fprintf, sprintf, etc. are
|
||||
assumed to lie in FLASH (string arguments for %s are still assumed
|
||||
to reside in SRAM). And (2), the string argument to puts and fputs
|
||||
is assumed to reside in FLASH. Clearly, these assumptions may have
|
||||
to modified for the particular needs of your environment. There
|
||||
is no "one-size-fits-all" solution for this problem.
|
||||
|
||||
Sizes of configurable things (0 disables)
|
||||
|
||||
|
@ -449,6 +449,45 @@ EXTERN void up_disable_irq(int irq);
|
||||
EXTERN int up_prioritize_irq(int irq, int priority);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_romgetc
|
||||
*
|
||||
* Description:
|
||||
* In Harvard architectures, data accesses and instruction accesses occur
|
||||
* on different busses, perhaps concurrently. All data accesses are
|
||||
* performed on the data bus unless special machine instructions are
|
||||
* used to read data from the instruction address space. Also, in the
|
||||
* typical MCU, the available SRAM data memory is much smaller that the
|
||||
* non-volatile FLASH instruction memory. So if the application requires
|
||||
* many constant strings, the only practical solution may be to store
|
||||
* those constant strings in FLASH memory where they can only be accessed
|
||||
* using architecture-specific machine instructions.
|
||||
*
|
||||
* A similar case is where strings are retained in "external" memory such
|
||||
* as EEPROM or serial FLASH. This case is similar only in that again
|
||||
* special operations are required to obtain the string data; it cannot
|
||||
* be accessed directly from a string pointer.
|
||||
*
|
||||
* If CONFIG_ARCH_ROMGETC is defined, then the architecture logic must
|
||||
* export the function up_romgetc(). up_romgetc() will simply read one
|
||||
* byte of data from the instruction space.
|
||||
*
|
||||
* If CONFIG_ARCH_ROMGETC, certain C stdio functions are effected: (1)
|
||||
* All format strings in printf, fprintf, sprintf, etc. are assumed to
|
||||
* lie in FLASH (string arguments for %s are still assumed to reside in
|
||||
* SRAM). And (2), the string argument to puts and fputs is assumed to
|
||||
* reside in FLASH. Clearly, these assumptions may have to modified for
|
||||
* the particular needs of your environment. There is no "one-size-fits-all"
|
||||
* solution for this problem.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_ROMGETC
|
||||
EXTERN char up_romgetc(FAR const char *ptr);
|
||||
#else
|
||||
# define up_romgetc(ptr) (*ptr)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_mdelay and up_udelay
|
||||
*
|
||||
|
@ -103,7 +103,7 @@
|
||||
* pointers are 16-bits.
|
||||
*/
|
||||
|
||||
#if defined(__m32c__) || defined(__AVR__)
|
||||
#if defined(__m32c__)
|
||||
/* Select the small, 16-bit addressing model */
|
||||
|
||||
# define CONFIG_SMALL_MEMORY 1
|
||||
@ -116,7 +116,24 @@
|
||||
|
||||
# undef CONFIG_PTR_IS_NOT_INT
|
||||
|
||||
/* Handle cases where sizeof(int) may or may not be 16-bits */
|
||||
#elif defined(__AVR__)
|
||||
/* Select the small, 16-bit addressing model */
|
||||
|
||||
# define CONFIG_SMALL_MEMORY 1
|
||||
|
||||
/* Long and int are not the same size */
|
||||
|
||||
# define CONFIG_LONG_IS_NOT_INT 1
|
||||
|
||||
/* Pointers and int are the same size */
|
||||
|
||||
# undef CONFIG_PTR_IS_NOT_INT
|
||||
|
||||
/* Uses a 32-bit FAR pointer only from accessing data outside of the 16-bit
|
||||
* data space.
|
||||
*/
|
||||
|
||||
# define CONFIG_HAVE_FARPOINTER 1
|
||||
|
||||
#elif defined(__mc68hc1x__)
|
||||
/* Select the small, 16-bit addressing model */
|
||||
|
@ -282,6 +282,15 @@ typedef _uint64_t uint_fast64_t;
|
||||
typedef _intptr_t intptr_t;
|
||||
typedef _uintptr_t uintptr_t;
|
||||
|
||||
/* Some architectures support a FAR pointer which is larger then the normal
|
||||
* (near) pointer
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_HAVE_FARPOINTER
|
||||
typedef _int_farptr_t int_farptr_t;
|
||||
typedef _uint_farptr_t uint_farptr_t;
|
||||
#endif
|
||||
|
||||
/* Greatest-width integer types */
|
||||
|
||||
#ifdef __INT64_DEFINED
|
||||
|
@ -124,7 +124,7 @@ extern int lib_sprintf(FAR struct lib_outstream_s *obj,
|
||||
/* Defined lib_libvsprintf.c */
|
||||
|
||||
extern int lib_vsprintf(FAR struct lib_outstream_s *obj,
|
||||
const char *src, va_list ap);
|
||||
FAR const char *src, va_list ap);
|
||||
|
||||
/* Defined lib_rawprintf.c */
|
||||
|
||||
|
@ -41,9 +41,14 @@
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include "lib_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
@ -90,7 +95,53 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_ARCH_ROMGETC)
|
||||
int fputs(FAR const char *s, FAR FILE *stream)
|
||||
{
|
||||
int nput;
|
||||
int ret;
|
||||
char ch;
|
||||
|
||||
/* Make sure that a string was provided. */
|
||||
|
||||
#ifdef CONFIG_DEBUG /* Most parameter checking is disabled if DEBUG is off */
|
||||
if (!s)
|
||||
{
|
||||
set_errno(EINVAL);
|
||||
return EOF;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Write the string. Loop until the null terminator is encountered */
|
||||
|
||||
for (nput = 0, ch = up_romgetc(s); ch; nput++, s++, ch = up_romgetc(s))
|
||||
{
|
||||
/* Write the next character to the stream buffer */
|
||||
|
||||
ret = lib_fwrite(&ch, 1, stream);
|
||||
if (ret <= 0)
|
||||
{
|
||||
return EOF;
|
||||
}
|
||||
|
||||
/* Flush the buffer if a newline was written to the buffer */
|
||||
|
||||
#ifdef CONFIG_STDIO_LINEBUFFER
|
||||
if (ch == '\n')
|
||||
{
|
||||
ret = lib_fflush(stream, true);
|
||||
if (ret < 0)
|
||||
{
|
||||
return EOF;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return nput;
|
||||
}
|
||||
|
||||
#elif defined(CONFIG_STDIO_LINEBUFFER)
|
||||
int fputs(FAR const char *s, FAR FILE *stream)
|
||||
{
|
||||
int nput;
|
||||
@ -118,7 +169,7 @@ int fputs(FAR const char *s, FAR FILE *stream)
|
||||
return EOF;
|
||||
}
|
||||
|
||||
/* Flush the buffer if a newline was writen to the buffer */
|
||||
/* Flush the buffer if a newline was written to the buffer */
|
||||
|
||||
if (*s == '\n')
|
||||
{
|
||||
|
@ -44,6 +44,8 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include "lib_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
@ -96,6 +98,33 @@ enum
|
||||
#define IS_NEGATE(f) (((f) & FLAG_NEGATE) != 0)
|
||||
#define IS_SIGNED(f) (((f) & (FLAG_SHOWPLUS|FLAG_NEGATE)) != 0)
|
||||
|
||||
/* If CONFIG_ARCH_ROMGETC is defined, then it is assumed that the format
|
||||
* string data cannot be accessed by simply de-referencing the format string
|
||||
* pointer. This might be in the case in Harvard architectures where string
|
||||
* data might be stored in instruction space or if string data were stored
|
||||
* on some media like EEPROM or external serial FLASH. In all of these cases,
|
||||
* string data has to be accessed indirectly using the architecture-supplied
|
||||
* up_romgetc(). The following mechanisms attempt to make these different
|
||||
* access methods indistinguishable in the following code.
|
||||
*
|
||||
* NOTE: It is assumed that string arguments for %s still reside in memory
|
||||
* that can be directly accessed by de-referencing the string pointer.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_ARCH_ROMGETC
|
||||
# define FMT_TOP ch = up_romgetc(src) /* Loop initialization */
|
||||
# define FMT_BOTTOM src++, ch = up_romgetc(src) /* Bottom of a loop */
|
||||
# define FMT_CHAR ch /* Access a character */
|
||||
# define FMT_NEXT src++; ch = up_romgetc(src) /* Advance to the next character */
|
||||
# define FMT_PREV src--; ch = up_romgetc(src) /* Backup to the previous character */
|
||||
#else
|
||||
# define FMT_TOP /* Loop initialization */
|
||||
# define FMT_BOTTOM src++ /* Bottom of a loop */
|
||||
# define FMT_CHAR *src /* Access a character */
|
||||
# define FMT_NEXT src++ /* Advance to the next character */
|
||||
# define FMT_PREV src-- /* Backup to the previous character */
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Type Declarations
|
||||
****************************************************************************/
|
||||
@ -1111,30 +1140,33 @@ static void postjustify(FAR struct lib_outstream_s *obj, uint8_t fmt,
|
||||
* lib/stdio/lib_vsprintf
|
||||
****************************************************************************/
|
||||
|
||||
int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const char *src, va_list ap)
|
||||
{
|
||||
char *ptmp;
|
||||
FAR char *ptmp;
|
||||
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
|
||||
int width;
|
||||
int trunc;
|
||||
uint8_t fmt;
|
||||
#endif
|
||||
uint8_t flags;
|
||||
#ifdef CONFIG_ARCH_ROMGETC
|
||||
char ch;
|
||||
#endif
|
||||
|
||||
for (; *src; src++)
|
||||
for (FMT_TOP; FMT_CHAR; FMT_BOTTOM)
|
||||
{
|
||||
/* Just copy regular characters */
|
||||
|
||||
if (*src != '%')
|
||||
if (FMT_CHAR != '%')
|
||||
{
|
||||
/* Output the character */
|
||||
|
||||
obj->put(obj, *src);
|
||||
obj->put(obj, FMT_CHAR);
|
||||
|
||||
/* Flush the buffer if a newline is encountered */
|
||||
|
||||
#ifdef CONFIG_STDIO_LINEBUFFER
|
||||
if (*src == '\n')
|
||||
if (FMT_CHAR == '\n')
|
||||
{
|
||||
/* Should return an error on a failure to flush */
|
||||
|
||||
@ -1148,7 +1180,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
|
||||
/* We have found a format specifier. Move past it. */
|
||||
|
||||
src++;
|
||||
FMT_NEXT;
|
||||
|
||||
/* Assume defaults */
|
||||
|
||||
@ -1161,18 +1193,18 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
|
||||
/* Process each format qualifier. */
|
||||
|
||||
for (; *src; src++)
|
||||
for (; FMT_CHAR; FMT_BOTTOM)
|
||||
{
|
||||
/* Break out of the loop when the format is known. */
|
||||
|
||||
if (strchr("diuxXpobeEfgGlLsc%", *src))
|
||||
if (strchr("diuxXpobeEfgGlLsc%", FMT_CHAR))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check for left justification. */
|
||||
|
||||
else if (*src == '-')
|
||||
else if (FMT_CHAR == '-')
|
||||
{
|
||||
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
|
||||
fmt = FMT_LJUST;
|
||||
@ -1181,7 +1213,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
|
||||
/* Check for leading zero fill right justification. */
|
||||
|
||||
else if (*src == '0')
|
||||
else if (FMT_CHAR == '0')
|
||||
{
|
||||
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
|
||||
fmt = FMT_RJUST0;
|
||||
@ -1190,7 +1222,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
#if 0
|
||||
/* Center justification. */
|
||||
|
||||
else if (*src == '~')
|
||||
else if (FMT_CHAR == '~')
|
||||
{
|
||||
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
|
||||
fmt = FMT_CENTER;
|
||||
@ -1198,7 +1230,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
}
|
||||
#endif
|
||||
|
||||
else if (*src == '*')
|
||||
else if (FMT_CHAR == '*')
|
||||
{
|
||||
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
|
||||
int value = va_arg(ap, int);
|
||||
@ -1217,17 +1249,29 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
|
||||
/* Check for field width */
|
||||
|
||||
else if (*src >= '1' && *src <= '9')
|
||||
else if (FMT_CHAR >= '1' && FMT_CHAR <= '9')
|
||||
{
|
||||
#ifdef CONFIG_NOPRINTF_FIELDWIDTH
|
||||
for (src++; (*src >= '0' && *src <= '9'); src++);
|
||||
do
|
||||
{
|
||||
FMT_NEXT;
|
||||
}
|
||||
while (FMT_CHAR >= '0' && FMT_CHAR <= '9');
|
||||
#else
|
||||
/* Accumulate the field width integer. */
|
||||
|
||||
int n = ((int)(*src)) - (int)'0';
|
||||
for (src++; (*src >= '0' && *src <= '9'); src++)
|
||||
int n = ((int)(FMT_CHAR)) - (int)'0';
|
||||
for (;;)
|
||||
{
|
||||
n = 10*n + (((int)(*src)) - (int)'0');
|
||||
FMT_NEXT;
|
||||
if (FMT_CHAR >= '0' && FMT_CHAR <= '9')
|
||||
{
|
||||
n = 10*n + (((int)(FMT_CHAR)) - (int)'0');
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_HASDOT(flags))
|
||||
@ -1241,12 +1285,12 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
#endif
|
||||
/* Back up to the last digit. */
|
||||
|
||||
src--;
|
||||
FMT_PREV;
|
||||
}
|
||||
|
||||
/* Check for a decimal point. */
|
||||
|
||||
else if (*src == '.')
|
||||
else if (FMT_CHAR == '.')
|
||||
{
|
||||
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
|
||||
SET_HASDOT(flags);
|
||||
@ -1255,14 +1299,14 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
|
||||
/* Check for leading plus sign. */
|
||||
|
||||
else if (*src == '+')
|
||||
else if (FMT_CHAR == '+')
|
||||
{
|
||||
SET_SHOWPLUS(flags);
|
||||
}
|
||||
|
||||
/* Check for alternate form. */
|
||||
|
||||
else if (*src == '#')
|
||||
else if (FMT_CHAR == '#')
|
||||
{
|
||||
SET_ALTFORM(flags);
|
||||
}
|
||||
@ -1272,7 +1316,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
* specification).
|
||||
*/
|
||||
|
||||
if (*src == '%')
|
||||
if (FMT_CHAR == '%')
|
||||
{
|
||||
obj->put(obj, '%');
|
||||
continue;
|
||||
@ -1280,7 +1324,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
|
||||
/* Check for the string format. */
|
||||
|
||||
if (*src == 's')
|
||||
if (FMT_CHAR == 's')
|
||||
{
|
||||
/* Just concatenate the string into the output */
|
||||
|
||||
@ -1300,7 +1344,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
|
||||
/* Check for the character output */
|
||||
|
||||
else if (*src == 'c')
|
||||
else if (FMT_CHAR == 'c')
|
||||
{
|
||||
/* Just copy the character into the output. */
|
||||
|
||||
@ -1311,27 +1355,28 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
|
||||
/* Check for the long long prefix. */
|
||||
|
||||
if (*src == 'L')
|
||||
if (FMT_CHAR == 'L')
|
||||
{
|
||||
SET_LONGLONGPRECISION(flags);
|
||||
++src;
|
||||
FMT_NEXT;
|
||||
}
|
||||
else if (*src == 'l')
|
||||
else if (FMT_CHAR == 'l')
|
||||
{
|
||||
SET_LONGPRECISION(flags);
|
||||
if (*++src == 'l')
|
||||
FMT_NEXT;
|
||||
if (FMT_CHAR == 'l')
|
||||
{
|
||||
SET_LONGLONGPRECISION(flags);
|
||||
++src;
|
||||
FMT_NEXT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle integer conversions */
|
||||
|
||||
if (strchr("diuxXpob", *src))
|
||||
if (strchr("diuxXpob", FMT_CHAR))
|
||||
{
|
||||
#ifdef CONFIG_HAVE_LONG_LONG
|
||||
if (IS_LONGLONGPRECISION(flags) && *src != 'p')
|
||||
if (IS_LONGLONGPRECISION(flags) && FMT_CHAR != 'p')
|
||||
{
|
||||
long long lln;
|
||||
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
|
||||
@ -1344,15 +1389,15 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
#ifdef CONFIG_NOPRINTF_FIELDWIDTH
|
||||
/* Output the number */
|
||||
|
||||
llutoascii(obj, *src, flags, (unsigned long long)lln);
|
||||
llutoascii(obj, FMT_CHAR, flags, (unsigned long long)lln);
|
||||
#else
|
||||
/* Resolve sign-ness and format issues */
|
||||
|
||||
llfixup(*src, &flags, &lln);
|
||||
llfixup(FMT_CHAR, &flags, &lln);
|
||||
|
||||
/* Get the width of the output */
|
||||
|
||||
lluwidth = getllusize(*src, flags, lln);
|
||||
lluwidth = getllusize(FMT_CHAR, flags, lln);
|
||||
|
||||
/* Perform left field justification actions */
|
||||
|
||||
@ -1360,7 +1405,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
|
||||
/* Output the number */
|
||||
|
||||
llutoascii(obj, *src, flags, (unsigned long long)lln);
|
||||
llutoascii(obj, FMT_CHAR, flags, (unsigned long long)lln);
|
||||
|
||||
/* Perform right field justification actions */
|
||||
|
||||
@ -1370,7 +1415,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
else
|
||||
#endif /* CONFIG_HAVE_LONG_LONG */
|
||||
#ifdef CONFIG_LONG_IS_NOT_INT
|
||||
if (IS_LONGPRECISION(flags) && *src != 'p')
|
||||
if (IS_LONGPRECISION(flags) && FMT_CHAR != 'p')
|
||||
{
|
||||
long ln;
|
||||
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
|
||||
@ -1383,15 +1428,15 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
#ifdef CONFIG_NOPRINTF_FIELDWIDTH
|
||||
/* Output the number */
|
||||
|
||||
lutoascii(obj, *src, flags, (unsigned long)ln);
|
||||
lutoascii(obj, FMT_CHAR, flags, (unsigned long)ln);
|
||||
#else
|
||||
/* Resolve sign-ness and format issues */
|
||||
|
||||
lfixup(*src, &flags, &ln);
|
||||
lfixup(FMT_CHAR, &flags, &ln);
|
||||
|
||||
/* Get the width of the output */
|
||||
|
||||
luwidth = getlusize(*src, flags, ln);
|
||||
luwidth = getlusize(FMT_CHAR, flags, ln);
|
||||
|
||||
/* Perform left field justification actions */
|
||||
|
||||
@ -1399,7 +1444,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
|
||||
/* Output the number */
|
||||
|
||||
lutoascii(obj, *src, flags, (unsigned long)ln);
|
||||
lutoascii(obj, FMT_CHAR, flags, (unsigned long)ln);
|
||||
|
||||
/* Perform right field justification actions */
|
||||
|
||||
@ -1409,7 +1454,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
else
|
||||
#endif /* CONFIG_LONG_IS_NOT_INT */
|
||||
#ifdef CONFIG_PTR_IS_NOT_INT
|
||||
if (*src == 'p')
|
||||
if (FMT_CHAR == 'p')
|
||||
{
|
||||
void *p;
|
||||
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
|
||||
@ -1426,11 +1471,11 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
#else
|
||||
/* Resolve sign-ness and format issues */
|
||||
|
||||
lfixup(*src, &flags, &ln);
|
||||
lfixup(FMT_CHAR, &flags, &ln);
|
||||
|
||||
/* Get the width of the output */
|
||||
|
||||
luwidth = getpsize(*src, flags, p);
|
||||
luwidth = getpsize(FMT_CHAR, flags, p);
|
||||
|
||||
/* Perform left field justification actions */
|
||||
|
||||
@ -1459,15 +1504,15 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
#ifdef CONFIG_NOPRINTF_FIELDWIDTH
|
||||
/* Output the number */
|
||||
|
||||
utoascii(obj, *src, flags, (unsigned int)n);
|
||||
utoascii(obj, FMT_CHAR, flags, (unsigned int)n);
|
||||
#else
|
||||
/* Resolve sign-ness and format issues */
|
||||
|
||||
fixup(*src, &flags, &n);
|
||||
fixup(FMT_CHAR, &flags, &n);
|
||||
|
||||
/* Get the width of the output */
|
||||
|
||||
uwidth = getusize(*src, flags, n);
|
||||
uwidth = getusize(FMT_CHAR, flags, n);
|
||||
|
||||
/* Perform left field justification actions */
|
||||
|
||||
@ -1475,7 +1520,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
|
||||
/* Output the number */
|
||||
|
||||
utoascii(obj, *src, flags, (unsigned int)n);
|
||||
utoascii(obj, FMT_CHAR, flags, (unsigned int)n);
|
||||
|
||||
/* Perform right field justification actions */
|
||||
|
||||
@ -1487,10 +1532,10 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, const char *src, va_list ap)
|
||||
/* Handle floating point conversions */
|
||||
|
||||
#ifdef CONFIG_LIBC_FLOATINGPOINT
|
||||
else if (strchr("eEfgG", *src))
|
||||
else if (strchr("eEfgG", FMT_CHAR))
|
||||
{
|
||||
double dblval = va_arg(ap, double);
|
||||
lib_dtoa(obj, *src, trunc, flags, dblval);
|
||||
lib_dtoa(obj, FMT_CHAR, trunc, flags, dblval);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user