Enhancements to chprintf().

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@12821 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2019-05-31 12:21:08 +00:00
parent 05c9b4ccb2
commit e3e1081b51
1 changed files with 98 additions and 37 deletions

View File

@ -54,8 +54,9 @@ static char *long_to_string_with_divisor(char *p,
do { do {
i = (int)(l % radix); i = (int)(l % radix);
i += '0'; i += '0';
if (i > '9') if (i > '9') {
i += 'A' - '0' - 10; i += 'A' - '0' - 10;
}
*--q = i; *--q = i;
l /= radix; l /= radix;
} while ((ll /= radix) != 0); } while ((ll /= radix) != 0);
@ -81,14 +82,16 @@ static const long pow10[FLOAT_PRECISION] = {
static char *ftoa(char *p, double num, unsigned long precision) { static char *ftoa(char *p, double num, unsigned long precision) {
long l; long l;
if ((precision == 0) || (precision > FLOAT_PRECISION)) if ((precision == 0) || (precision > FLOAT_PRECISION)) {
precision = FLOAT_PRECISION; precision = FLOAT_PRECISION;
}
precision = pow10[precision - 1]; precision = pow10[precision - 1];
l = (long)num; l = (long)num;
p = long_to_string_with_divisor(p, l, 10, 0); p = long_to_string_with_divisor(p, l, 10, 0);
*p++ = '.'; *p++ = '.';
l = (long)((num - l) * precision); l = (long)((num - l) * precision);
return long_to_string_with_divisor(p, l, 10, precision / 10); return long_to_string_with_divisor(p, l, 10, precision / 10);
} }
#endif #endif
@ -123,7 +126,7 @@ int chvprintf(BaseSequentialStream *chp, const char *fmt, va_list ap) {
char *p, *s, c, filler; char *p, *s, c, filler;
int i, precision, width; int i, precision, width;
int n = 0; int n = 0;
bool is_long, left_align; bool is_long, left_align, do_sign;
long l; long l;
#if CHPRINTF_USE_FLOAT #if CHPRINTF_USE_FLOAT
float f; float f;
@ -134,58 +137,99 @@ int chvprintf(BaseSequentialStream *chp, const char *fmt, va_list ap) {
while (true) { while (true) {
c = *fmt++; c = *fmt++;
if (c == 0) if (c == 0) {
return n; return n;
}
if (c != '%') { if (c != '%') {
streamPut(chp, (uint8_t)c); streamPut(chp, (uint8_t)c);
n++; n++;
continue; continue;
} }
p = tmpbuf; p = tmpbuf;
s = tmpbuf; s = tmpbuf;
left_align = FALSE;
/* Alignment mode.*/
left_align = false;
if (*fmt == '-') { if (*fmt == '-') {
fmt++; fmt++;
left_align = TRUE; left_align = true;
} }
/* Sign mode.*/
do_sign = false;
if (*fmt == '+') {
fmt++;
do_sign = true;
}
/* Filler mode.*/
filler = ' '; filler = ' ';
if (*fmt == '0') { if (*fmt == '0') {
fmt++; fmt++;
filler = '0'; filler = '0';
} }
width = 0;
while (TRUE) { /* Width modifier.*/
c = *fmt++; if (c == '*') {
if (c >= '0' && c <= '9') width = va_arg(ap, int);
c -= '0';
else if (c == '*')
c = va_arg(ap, int);
else
break;
width = width * 10 + c;
} }
precision = 0; else {
if (c == '.') { width = 0;
while (TRUE) { while (true) {
c = *fmt++; c = *fmt++;
if (c >= '0' && c <= '9') if (c == 0) {
return n;
}
if (c >= '0' && c <= '9') {
c -= '0'; c -= '0';
else if (c == '*') width = width * 10 + c;
c = va_arg(ap, int); }
else else {
break; break;
precision *= 10; }
precision += c;
} }
} }
/* Precision modifier.*/
precision = 0;
if (c == '.') {
c = *fmt++;
if (c == 0) {
return n;
}
if (c == '*') {
precision = va_arg(ap, int);
}
else {
while (true) {
c = *fmt++;
if (c == 0) {
return n;
}
if (c >= '0' && c <= '9') {
c -= '0';
precision = precision * 10 + c;
}
else {
break;
}
}
}
}
/* Long modifier.*/ /* Long modifier.*/
if (c == 'l' || c == 'L') { if (c == 'l' || c == 'L') {
is_long = TRUE; is_long = true;
if (*fmt) c = *fmt++;
c = *fmt++; if (c == 0) {
return n;
}
} }
else else {
is_long = (c >= 'A') && (c <= 'Z'); is_long = (c >= 'A') && (c <= 'Z');
}
/* Command decoding.*/ /* Command decoding.*/
switch (c) { switch (c) {
@ -195,10 +239,12 @@ int chvprintf(BaseSequentialStream *chp, const char *fmt, va_list ap) {
break; break;
case 's': case 's':
filler = ' '; filler = ' ';
if ((s = va_arg(ap, char *)) == 0) if ((s = va_arg(ap, char *)) == 0) {
s = "(null)"; s = "(null)";
if (precision == 0) }
if (precision == 0) {
precision = 32767; precision = 32767;
}
for (p = s; *p && (--precision >= 0); p++) for (p = s; *p && (--precision >= 0); p++)
; ;
break; break;
@ -206,14 +252,20 @@ int chvprintf(BaseSequentialStream *chp, const char *fmt, va_list ap) {
case 'd': case 'd':
case 'I': case 'I':
case 'i': case 'i':
if (is_long) if (is_long) {
l = va_arg(ap, long); l = va_arg(ap, long);
else }
else {
l = va_arg(ap, int); l = va_arg(ap, int);
}
if (l < 0) { if (l < 0) {
*p++ = '-'; *p++ = '-';
l = -l; l = -l;
} }
else
if (do_sign) {
*p++ = '+';
}
p = ch_ltoa(p, l, 10); p = ch_ltoa(p, l, 10);
break; break;
#if CHPRINTF_USE_FLOAT #if CHPRINTF_USE_FLOAT
@ -223,6 +275,11 @@ int chvprintf(BaseSequentialStream *chp, const char *fmt, va_list ap) {
*p++ = '-'; *p++ = '-';
f = -f; f = -f;
} }
else {
if (do_sign) {
*p++ = '+';
}
}
p = ftoa(p, f, precision); p = ftoa(p, f, precision);
break; break;
#endif #endif
@ -238,10 +295,12 @@ int chvprintf(BaseSequentialStream *chp, const char *fmt, va_list ap) {
case 'o': case 'o':
c = 8; c = 8;
unsigned_common: unsigned_common:
if (is_long) if (is_long) {
l = va_arg(ap, unsigned long); l = va_arg(ap, unsigned long);
else }
else {
l = va_arg(ap, unsigned int); l = va_arg(ap, unsigned int);
}
p = ch_ltoa(p, l, c); p = ch_ltoa(p, l, c);
break; break;
default: default:
@ -249,10 +308,12 @@ unsigned_common:
break; break;
} }
i = (int)(p - s); i = (int)(p - s);
if ((width -= i) < 0) if ((width -= i) < 0) {
width = 0; width = 0;
if (left_align == FALSE) }
if (left_align == false) {
width = -width; width = -width;
}
if (width < 0) { if (width < 0) {
if (*s == '-' && filler == '0') { if (*s == '-' && filler == '0') {
streamPut(chp, (uint8_t)*s++); streamPut(chp, (uint8_t)*s++);