From e6c8a184b97dfa417692ea1a54c613235d73b756 Mon Sep 17 00:00:00 2001
From: patacongo
Date: Fri, 1 Jul 2011 19:08:04 +0000
Subject: [PATCH] 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
---
ChangeLog | 8 ++
Documentation/NuttxPortingGuide.html | 57 ++++++++---
arch/avr/include/avr/types.h | 7 +-
arch/avr/src/at90usb/Make.defs | 4 +
arch/avr/src/atmega/Make.defs | 4 +
arch/sim/src/Makefile | 6 ++
configs/README.txt | 34 ++++++-
include/nuttx/arch.h | 39 +++++++
include/nuttx/compiler.h | 21 +++-
include/stdint.h | 9 ++
lib/lib_internal.h | 2 +-
lib/stdio/lib_fputs.c | 53 +++++++++-
lib/stdio/lib_libvsprintf.c | 145 ++++++++++++++++++---------
13 files changed, 316 insertions(+), 73 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 51b317e0ac..7e210c8d7a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/Documentation/NuttxPortingGuide.html b/Documentation/NuttxPortingGuide.html
index e4bcc5d64e..f0bc051610 100644
--- a/Documentation/NuttxPortingGuide.html
+++ b/Documentation/NuttxPortingGuide.html
@@ -12,7 +12,7 @@
NuttX RTOS Porting Guide
- Last Updated: June 18, 2011
+ Last Updated: July 1, 2011
@@ -3628,34 +3628,65 @@ build
-
-
CONFIG_NOPRINTF_FIELDWIDTH
: sprintf-related logic is a
+ CONFIG_NOPRINTF_FIELDWIDTH
: sprintf
-related logic is a
little smaller if we do not support fieldwidthes
-
CONFIG_LIBC_FLOATINGPOINT
: By default, floating point
- support in printf, sscanf, etc. is disabled.
+ support in printf
, sscanf
, etc. is disabled.
Allow for architecture optimized implementations
-
- The architecture can provide optimized versions of the following to improve system performance.
-
-
-
+
-
+ 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
-
-
+
+
+-
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_ROMGETC
:
+ There are cases where string data cannot be cannot be accessed by simply de-referencing a string pointer.
+ As examples:
+
+
+ -
+ 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-specific 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)
diff --git a/arch/avr/include/avr/types.h b/arch/avr/include/avr/types.h
index 2dd35a5cb2..e0a70fb7f9 100644
--- a/arch/avr/include/avr/types.h
+++ b/arch/avr/include/avr/types.h
@@ -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;
diff --git a/arch/avr/src/at90usb/Make.defs b/arch/avr/src/at90usb/Make.defs
index 5b939f5afc..0497acd950 100644
--- a/arch/avr/src/at90usb/Make.defs
+++ b/arch/avr/src/at90usb/Make.defs
@@ -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
diff --git a/arch/avr/src/atmega/Make.defs b/arch/avr/src/atmega/Make.defs
index 47683fcd08..b3451aaa1f 100644
--- a/arch/avr/src/atmega/Make.defs
+++ b/arch/avr/src/atmega/Make.defs
@@ -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
diff --git a/arch/sim/src/Makefile b/arch/sim/src/Makefile
index 8e2fc56de9..f32f17b010 100644
--- a/arch/sim/src/Makefile
+++ b/arch/sim/src/Makefile
@@ -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)
diff --git a/configs/README.txt b/configs/README.txt
index 6c3a0b74a9..21426362f8 100644
--- a/configs/README.txt
+++ b/configs/README.txt
@@ -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)
diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h
index df9f1e9ab5..448af11052 100644
--- a/include/nuttx/arch.h
+++ b/include/nuttx/arch.h
@@ -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
*
diff --git a/include/nuttx/compiler.h b/include/nuttx/compiler.h
index c44ff329e9..c672054dd5 100644
--- a/include/nuttx/compiler.h
+++ b/include/nuttx/compiler.h
@@ -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 */
diff --git a/include/stdint.h b/include/stdint.h
index f6d2fcfcd3..26bcce4dba 100755
--- a/include/stdint.h
+++ b/include/stdint.h
@@ -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
diff --git a/lib/lib_internal.h b/lib/lib_internal.h
index 6c9b9c14c7..d960d6cf37 100644
--- a/lib/lib_internal.h
+++ b/lib/lib_internal.h
@@ -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 */
diff --git a/lib/stdio/lib_fputs.c b/lib/stdio/lib_fputs.c
index a2b132f2fc..34d12c15ea 100644
--- a/lib/stdio/lib_fputs.c
+++ b/lib/stdio/lib_fputs.c
@@ -41,9 +41,14 @@
* Included Files
****************************************************************************/
+#include
+
#include
#include
#include
+
+#include
+
#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')
{
diff --git a/lib/stdio/lib_libvsprintf.c b/lib/stdio/lib_libvsprintf.c
index 34a27ea4e3..3bc112e92f 100644
--- a/lib/stdio/lib_libvsprintf.c
+++ b/lib/stdio/lib_libvsprintf.c
@@ -44,6 +44,8 @@
#include
#include
+#include
+
#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
}