From fdf08e2a4114e559e58bd067c817fe9079bc9bcf Mon Sep 17 00:00:00 2001 From: gdisirio Date: Mon, 27 Jun 2011 15:00:05 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3091 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/various/chprintf.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 os/various/chprintf.c (limited to 'os/various/chprintf.c') diff --git a/os/various/chprintf.c b/os/various/chprintf.c new file mode 100644 index 000000000..2d210b5cb --- /dev/null +++ b/os/various/chprintf.c @@ -0,0 +1,238 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT 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 3 of the License, or + (at your option) any later version. + + ChibiOS/RT 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, see . +*/ + +#include + +#include "ch.h" + +#define MAXDIG 11 + +static char *itoa(char *p, int num, unsigned radix) { + int i; + char *q; + + q = p + MAXDIG; + do { + i = (int)(num % radix); + i += '0'; + if (i > '9') + i += 'A' - '0' - 10; + *--q = i; + } while ((num /= radix) != 0); + + i = (int)(p + MAXDIG - q); + do + *p++ = *q++; + while (--i); + + return p; +} + +#ifndef NO_LONGD + +static char *ltoa(char *p, long num, unsigned radix) { + int i; + char *q; + + q = p + MAXDIG; + do { + i = (int)(num % radix); + i += '0'; + if (i > '9') + i += 'A' - '0' - 10; + *--q = i; + } while ((num /= radix) != 0); + + i = (int)(p + MAXDIG - q); + do + *p++ = *q++; + while (--i); + + return p; +} +#endif + +void chprintf(BaseChannel *chp, const char *fmt, ...) { + va_list ap; + char buf[MAXDIG + 1]; + char *p, *s; + int c, i, width, ndigit, ndfnd, ljust, zfill; +#ifndef NO_LONGD + int lflag; + long l; +#endif + + va_start(ap, fmt); + while (TRUE) { + c = *fmt++; + if (c == 0) { + va_end(ap); + return; + } + if (c != '%') { + chIOPut(chp, (uint8_t)c); + continue; + } + p = buf; + s = buf; + ljust = 0; + if (*fmt == '-') { + fmt++; + ljust++; + } + zfill = ' '; + if (*fmt == '0') { + fmt++; + zfill = '0'; + } + for (width = 0;;) { + c = *fmt++; + if (c >= '0' && c <= '9') + c -= '0'; + else if (c == '*') + c = va_arg(ap, int); + else + break; + width *= 10; + width += c; + } + ndfnd = 0; + ndigit = 0; + if (c == '.') { + for (;;) { + c = *fmt++; + if (c >= '0' && c <= '9') + c -= '0'; + else if (c == '*') + c = va_arg(ap, int); + else + break; + ndigit *= 10; + ndigit += c; + ndfnd++; + } + } +#ifndef NO_LONGD + lflag = 0; +#endif + if (c == 'l' || c == 'L') { +#ifndef NO_LONGD + lflag++; +#endif + if (*fmt) + c = *fmt++; + } + switch (c) { + case 'X': +#ifndef NO_LONGD + lflag++; +#endif + case 'x': + c = 16; + goto oxu; + case 'U': +#ifndef NO_LONGD + lflag++; +#endif + case 'u': + c = 10; + goto oxu; + case 'O': +#ifndef NO_LONGD + lflag++; +#endif + case 'o': + c = 8; + oxu: +#ifndef NO_LONGD + if (lflag) { + p = ltoa(p, va_arg(ap, long), c); + break; + } +#endif + p = itoa(p, va_arg(ap, int), c); + break; + case 'D': +#ifndef NO_LONGD + lflag++; +#endif + case 'd': +#ifndef NO_LONGD + if (lflag) { + if ((l = va_arg(ap, long)) < 0) { + *p++ = '-'; + l = -l; + } + p = ltoa(p, l, 10); + break; + } +#endif + if ((i = va_arg(ap, int)) < 0) { + *p++ = '-'; + i = -i; + } + p = itoa(p, i, 10); + break; +/* case 'e': + case 'f': + case 'g': + zfill = ' '; + *p++ = '?'; + break;*/ + case 'c': + zfill = ' '; + *p++ = va_arg(ap, int); + break; + case 's': + zfill = ' '; + if ((s = va_arg(ap, char *)) == 0) + s = "(null)"; + if (ndigit == 0) + ndigit = 32767; + for (p = s; *p && --ndigit >= 0; p++) + ; + break; + default: + *p++ = c; + break; + } + i = (int)(p - s); + if ((width -= i) < 0) + width = 0; + if (ljust == 0) + width = -width; + if (width < 0) { + if (*s == '-' && zfill == '0') { + chIOPut(chp, (uint8_t)*s++); + i--; + } + do + chIOPut(chp, (uint8_t)zfill); + while (++width != 0); + } + while (--i >= 0) + chIOPut(chp, (uint8_t)*s++); + + while (width) { + chIOPut(chp, (uint8_t)zfill); + width--; + } + } +} -- cgit v1.2.3 From e10edf16834d7dbe0c4ce7ea88c634e31b7d3113 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Mon, 27 Jun 2011 19:57:11 +0000 Subject: Dedicated printf implementation. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3092 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/various/chprintf.c | 167 +++++++++++++++++--------------------------------- 1 file changed, 56 insertions(+), 111 deletions(-) (limited to 'os/various/chprintf.c') diff --git a/os/various/chprintf.c b/os/various/chprintf.c index 2d210b5cb..383a2121a 100644 --- a/os/various/chprintf.c +++ b/os/various/chprintf.c @@ -1,83 +1,57 @@ /* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011 Giovanni Di Sirio. - This file is part of ChibiOS/RT. + This file is part of ChibiOS/RT. - ChibiOS/RT 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 3 of the License, or - (at your option) any later version. + ChibiOS/RT 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 3 of the License, or + (at your option) any later version. - ChibiOS/RT 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. + ChibiOS/RT 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, see . -*/ + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ #include #include "ch.h" -#define MAXDIG 11 - -static char *itoa(char *p, int num, unsigned radix) { - int i; - char *q; - - q = p + MAXDIG; - do { - i = (int)(num % radix); - i += '0'; - if (i > '9') - i += 'A' - '0' - 10; - *--q = i; - } while ((num /= radix) != 0); - - i = (int)(p + MAXDIG - q); - do - *p++ = *q++; - while (--i); - - return p; -} - -#ifndef NO_LONGD +#define MAX_FILLER 11 static char *ltoa(char *p, long num, unsigned radix) { int i; char *q; - q = p + MAXDIG; + q = p + MAX_FILLER; do { i = (int)(num % radix); i += '0'; if (i > '9') - i += 'A' - '0' - 10; + i += 'A' - '0' - 10; *--q = i; } while ((num /= radix) != 0); - i = (int)(p + MAXDIG - q); + i = (int)(p + MAX_FILLER - q); do *p++ = *q++; while (--i); return p; } -#endif void chprintf(BaseChannel *chp, const char *fmt, ...) { va_list ap; - char buf[MAXDIG + 1]; - char *p, *s; - int c, i, width, ndigit, ndfnd, ljust, zfill; -#ifndef NO_LONGD - int lflag; + char buf[MAX_FILLER + 1]; + char *p, *s, c, filler; + int i, n, width; + bool_t lflag, ljust; long l; -#endif va_start(ap, fmt); while (TRUE) { @@ -92,15 +66,15 @@ void chprintf(BaseChannel *chp, const char *fmt, ...) { } p = buf; s = buf; - ljust = 0; + ljust = FALSE; if (*fmt == '-') { fmt++; - ljust++; + ljust = TRUE; } - zfill = ' '; - if (*fmt == '0') { + filler = ' '; + if (*fmt == '.') { fmt++; - zfill = '0'; + filler = '0'; } for (width = 0;;) { c = *fmt++; @@ -113,8 +87,7 @@ void chprintf(BaseChannel *chp, const char *fmt, ...) { width *= 10; width += c; } - ndfnd = 0; - ndigit = 0; + n = 0; if (c == '.') { for (;;) { c = *fmt++; @@ -124,89 +97,61 @@ void chprintf(BaseChannel *chp, const char *fmt, ...) { c = va_arg(ap, int); else break; - ndigit *= 10; - ndigit += c; - ndfnd++; + n *= 10; + n += c; } } -#ifndef NO_LONGD - lflag = 0; -#endif + lflag = FALSE; if (c == 'l' || c == 'L') { -#ifndef NO_LONGD lflag++; -#endif if (*fmt) c = *fmt++; } switch (c) { case 'X': -#ifndef NO_LONGD - lflag++; -#endif + lflag = TRUE; case 'x': c = 16; goto oxu; case 'U': -#ifndef NO_LONGD - lflag++; -#endif + lflag = TRUE; case 'u': c = 10; goto oxu; case 'O': -#ifndef NO_LONGD - lflag++; -#endif + lflag = TRUE; case 'o': c = 8; - oxu: -#ifndef NO_LONGD - if (lflag) { - p = ltoa(p, va_arg(ap, long), c); - break; - } -#endif - p = itoa(p, va_arg(ap, int), c); + oxu: if (lflag) + l = va_arg(ap, long); + else + l = va_arg(ap, int); + p = ltoa(p, l, c); break; case 'D': -#ifndef NO_LONGD - lflag++; -#endif + lflag = TRUE; case 'd': -#ifndef NO_LONGD - if (lflag) { - if ((l = va_arg(ap, long)) < 0) { - *p++ = '-'; - l = -l; - } - p = ltoa(p, l, 10); - break; - } -#endif - if ((i = va_arg(ap, int)) < 0) { + if (lflag) + l = va_arg(ap, long); + else + l = va_arg(ap, int); + if (l < 0) { *p++ = '-'; - i = -i; + l = -l; } - p = itoa(p, i, 10); + p = ltoa(p, l, 10); break; -/* case 'e': - case 'f': - case 'g': - zfill = ' '; - *p++ = '?'; - break;*/ case 'c': - zfill = ' '; + filler = ' '; *p++ = va_arg(ap, int); break; case 's': - zfill = ' '; + filler = ' '; if ((s = va_arg(ap, char *)) == 0) s = "(null)"; - if (ndigit == 0) - ndigit = 32767; - for (p = s; *p && --ndigit >= 0; p++) + if (n == 0) + n = 32767; + for (p = s; *p && --n >= 0; p++) ; break; default: @@ -216,22 +161,22 @@ void chprintf(BaseChannel *chp, const char *fmt, ...) { i = (int)(p - s); if ((width -= i) < 0) width = 0; - if (ljust == 0) + if (ljust == FALSE) width = -width; if (width < 0) { - if (*s == '-' && zfill == '0') { + if (*s == '-' && filler == '0') { chIOPut(chp, (uint8_t)*s++); i--; } do - chIOPut(chp, (uint8_t)zfill); + chIOPut(chp, (uint8_t)filler); while (++width != 0); } while (--i >= 0) chIOPut(chp, (uint8_t)*s++); while (width) { - chIOPut(chp, (uint8_t)zfill); + chIOPut(chp, (uint8_t)filler); width--; } } -- cgit v1.2.3 From ddc9ded3f065d8da59a843390814b1c19061c566 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Tue, 28 Jun 2011 06:29:04 +0000 Subject: chprintf() implemented, improved the shell. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3093 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/various/chprintf.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'os/various/chprintf.c') diff --git a/os/various/chprintf.c b/os/various/chprintf.c index 383a2121a..1645cd678 100644 --- a/os/various/chprintf.c +++ b/os/various/chprintf.c @@ -45,6 +45,29 @@ static char *ltoa(char *p, long num, unsigned radix) { return p; } +/** + * @brief System formatted output function. + * @details This function implements a minimal @p printf() like functionality + * with output on a @p BaseChannel. + * The general parameters format is: %[.][width|*][l|L]p. + * The following parameter types (p) are supported: + * - x hexadecimal integer. + * - X hexadecimal long. + * - o octal integer. + * - O octal long. + * - d decimal signed integer. + * - D decimal signed long. + * - u decimal unsigned integer. + * - U decimal unsigned long. + * - c character. + * - s string. + * . + * @note Floating point types are not implemented, this function is meant + * as a system utility and not a full implementation. + * + * @param[in] chp pointer to a @p BaseChannel implementing object + * @param[in] fmt formatting string + */ void chprintf(BaseChannel *chp, const char *fmt, ...) { va_list ap; char buf[MAX_FILLER + 1]; @@ -84,8 +107,7 @@ void chprintf(BaseChannel *chp, const char *fmt, ...) { c = va_arg(ap, int); else break; - width *= 10; - width += c; + width = width * 10 + c; } n = 0; if (c == '.') { @@ -122,7 +144,8 @@ void chprintf(BaseChannel *chp, const char *fmt, ...) { lflag = TRUE; case 'o': c = 8; - oxu: if (lflag) +oxu: + if (lflag) l = va_arg(ap, long); else l = va_arg(ap, int); -- cgit v1.2.3