summaryrefslogtreecommitdiff
path: root/nuttx/lib/stdio
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-07-01 19:08:04 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-07-01 19:08:04 +0000
commit00b2545e9e3cc760255aa7b4fc953ad5ab97ba62 (patch)
tree90f908d15691555fdf19c21eeae7b55187b73803 /nuttx/lib/stdio
parent6e09d7aab47a47e36f56d9b33bd6e87e96e2af2c (diff)
downloadpx4-nuttx-00b2545e9e3cc760255aa7b4fc953ad5ab97ba62.tar.gz
px4-nuttx-00b2545e9e3cc760255aa7b4fc953ad5ab97ba62.tar.bz2
px4-nuttx-00b2545e9e3cc760255aa7b4fc953ad5ab97ba62.zip
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
Diffstat (limited to 'nuttx/lib/stdio')
-rw-r--r--nuttx/lib/stdio/lib_fputs.c53
-rw-r--r--nuttx/lib/stdio/lib_libvsprintf.c145
2 files changed, 147 insertions, 51 deletions
diff --git a/nuttx/lib/stdio/lib_fputs.c b/nuttx/lib/stdio/lib_fputs.c
index a2b132f2f..34d12c15e 100644
--- a/nuttx/lib/stdio/lib_fputs.c
+++ b/nuttx/lib/stdio/lib_fputs.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')
{
diff --git a/nuttx/lib/stdio/lib_libvsprintf.c b/nuttx/lib/stdio/lib_libvsprintf.c
index 34a27ea4e..3bc112e92 100644
--- a/nuttx/lib/stdio/lib_libvsprintf.c
+++ b/nuttx/lib/stdio/lib_libvsprintf.c
@@ -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
}