Page 1 of 1

chsprintf minimal @p sprintf() patch

Posted: Mon Dec 02, 2013 4:43 pm
by tdwebste
We have added chsprint to implement a minimal @p sprintf() like functionality with
output to a string.


Your feed back is appreciated.

How do I attach a patch file? I am getting The extension " " is not allowed for everything I have tried.


From 8a4411d184dc884a9a3e03a1a7fa54356d6d0dbd Mon Sep 17 00:00:00 2001
From: Timothy Webster <[email protected]>
Date: Sun, 1 Dec 2013 23:33:22 -0500
Subject: [PATCH] chibios sprint

chsprintf
This function implements a minimal @p sprintf() like functionality with
output to a string.
---
os/various/chprintf.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 176 insertions(+)

diff --git a/os/various/chprintf.c b/os/various/chprintf.c
index 5d3d38e..0960eaa 100644
--- a/os/various/chprintf.c
+++ b/os/various/chprintf.c
@@ -259,4 +259,180 @@ unsigned_common:
}
}

+/**
+ * @brief Formatted string function.
+ * @details This function implements a minimal @p sprintf() like functionality
+ * with output to a string.
+ * The general parameters format is: %[-][width|*][.precision|*][l|L]p.
+ * The following parameter types (p) are supported:
+ * - <b>x</b> hexadecimal integer.
+ * - <b>X</b> hexadecimal long.
+ * - <b>o</b> octal integer.
+ * - <b>O</b> octal long.
+ * - <b>d</b> decimal signed integer.
+ * - <b>D</b> decimal signed long.
+ * - <b>u</b> decimal unsigned integer.
+ * - <b>U</b> decimal unsigned long.
+ * - <b>c</b> character.
+ * - <b>s</b> string.
+ * .
+ *
+ * @param[in] buf pointer to a string buffer
+ * @param[in] fmt formatting string
+ */
+void chsprintf(char *buf, const char *fmt, ...) {
+ va_list ap;
+ char *p, *s, c, filler;
+ int i, precision, width;
+ bool_t is_long, left_align;
+ long l;
+#if CHPRINTF_USE_FLOAT
+ float f;
+ char tmpbuf[2*MAX_FILLER + 1];
+#else
+ char tmpbuf[MAX_FILLER + 1];
+#endif
+
+ va_start(ap, fmt);
+ while (TRUE) {
+ c = *fmt++;
+ if (c == 0) {
+ va_end(ap);
+ *(buf++) = 0;
+ return;
+ }
+ if (c != '%') {
+ *(buf++) = (uint8_t)c;
+ continue;
+ }
+ p = tmpbuf;
+ s = tmpbuf;
+ left_align = FALSE;
+ if (*fmt == '-') {
+ fmt++;
+ left_align = TRUE;
+ }
+ filler = ' ';
+ if (*fmt == '.') {
+ fmt++;
+ filler = '0';
+ }
+ width = 0;
+ while (TRUE) {
+ c = *fmt++;
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c == '*')
+ c = va_arg(ap, int);
+ else
+ break;
+ width = width * 10 + c;
+ }
+ precision = 0;
+ if (c == '.') {
+ while (TRUE) {
+ c = *fmt++;
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c == '*')
+ c = va_arg(ap, int);
+ else
+ break;
+ precision *= 10;
+ precision += c;
+ }
+ }
+ /* Long modifier.*/
+ if (c == 'l' || c == 'L') {
+ is_long = TRUE;
+ if (*fmt)
+ c = *fmt++;
+ }
+ else
+ is_long = (c >= 'A') && (c <= 'Z');
+
+ /* Command decoding.*/
+ switch (c) {
+ case 'c':
+ filler = ' ';
+ *p++ = va_arg(ap, int);
+ break;
+ case 's':
+ filler = ' ';
+ if ((s = va_arg(ap, char *)) == 0)
+ s = "(null)";
+ if (precision == 0)
+ precision = 32767;
+ for (p = s; *p && (--precision >= 0); p++)
+ ;
+ break;
+ case 'D':
+ case 'd':
+ case 'I':
+ case 'i':
+ if (is_long)
+ l = va_arg(ap, long);
+ else
+ l = va_arg(ap, int);
+ if (l < 0) {
+ *p++ = '-';
+ l = -l;
+ }
+ p = ltoa(p, l, 10);
+ break;
+#if CHPRINTF_USE_FLOAT
+ case 'f':
+ f = (float) va_arg(ap, double);
+ if (f < 0) {
+ *p++ = '-';
+ f = -f;
+ }
+ p = ftoa(p, f);
+ break;
+#endif
+ case 'X':
+ case 'x':
+ c = 16;
+ goto unsigned_common;
+ case 'U':
+ case 'u':
+ c = 10;
+ goto unsigned_common;
+ case 'O':
+ case 'o':
+ c = 8;
+unsigned_common:
+ if (is_long)
+ l = va_arg(ap, unsigned long);
+ else
+ l = va_arg(ap, unsigned int);
+ p = ltoa(p, l, c);
+ break;
+ default:
+ *p++ = c;
+ break;
+ }
+ i = (int)(p - s);
+ if ((width -= i) < 0)
+ width = 0;
+ if (left_align == FALSE)
+ width = -width;
+ if (width < 0) {
+ if (*s == '-' && filler == '0') {
+ *(buf++) = (uint8_t)*s++;
+ i--;
+ }
+ do
+ *(buf++) = (uint8_t)filler;
+ while (++width != 0);
+ }
+ while (--i >= 0)
+ *(buf++) = (uint8_t)*s++;
+
+ while (width) {
+ *(buf++) = (uint8_t)filler;
+ width--;
+ }
+ }
+}
/** @} */
--
1.8.1.2

Re: chsprintf minimal @p sprintf() patch

Posted: Mon Dec 02, 2013 5:23 pm
by Giovanni
Hi,

I need to verify if there is an easier way to implement chsprintf(), duplicating all the code looks a bit wasteful. Probably it is possible to create a string writer implementing a stream and using the normal chprintf() for printing.

Giovanni

Re: chsprintf minimal @p sprintf() patch

Posted: Tue Dec 03, 2013 10:39 am
by Giovanni
Hi,

I added an alternate implementation of chsnprintf() that uses memstreams internally. Note the "N", I prefer this variant for safety reasons.

Please let me go if it works for you.

Giovanni

Re: chsprintf minimal @p sprintf() patch

Posted: Wed Dec 04, 2013 1:29 am
by tdwebste
Thx
Which release repository did you add it to? 2.6 or 2.7.
We are still on 2.6, But we are looking to migrate to 2.7

Re: chsprintf minimal @p sprintf() patch

Posted: Wed Dec 04, 2013 12:31 pm
by Giovanni
Hi,

Both, it will be in 2.6.2 and 2.7.0.

Note that 2.7.0 probably will never be released and replaced by the 3.0.0 branch. Everything is going in 2.6.2 anyway.

Giovanni

Re: chsprintf minimal @p sprintf() patch

Posted: Fri Dec 06, 2013 10:40 pm
by tdwebste
I know I am missing something easy.

git grep include -- 'chprintf.[ch]'
chprintf.c:#include "ch.h"
chprintf.c:#include "chprintf.h"
chprintf.c:#include "memstreams.h"
chprintf.h:#include <stdarg.h>


chprintf.c:297: undefined reference to `msObjectInit'

ideas?

Re: chsprintf minimal @p sprintf() patch

Posted: Sat Dec 07, 2013 2:02 am
by tdwebste
Forgot to add
$(CHIBIOS)/os/various/memstreams.c \
to my Makefile.