fix rt_kprint 64bit error

This commit is contained in:
zhkag 2023-02-20 18:14:34 +08:00 committed by guo
parent 1c2daeafdc
commit feed84b258
1 changed files with 182 additions and 64 deletions

View File

@ -41,6 +41,7 @@
/* use precision */ /* use precision */
#define RT_PRINTF_PRECISION #define RT_PRINTF_PRECISION
#define RT_PRINTF_SPECIAL
/** /**
* @addtogroup KernelService * @addtogroup KernelService
@ -688,20 +689,20 @@ RTM_EXPORT(rt_show_version);
* @return the duplicated string pointer. * @return the duplicated string pointer.
*/ */
#ifdef RT_KPRINTF_USING_LONGLONG #ifdef RT_KPRINTF_USING_LONGLONG
rt_inline int divide(long long *n, int base) rt_inline int divide(unsigned long long *n, int base)
#else #else
rt_inline int divide(long *n, int base) rt_inline int divide(unsigned long *n, int base)
#endif /* RT_KPRINTF_USING_LONGLONG */ #endif /* RT_KPRINTF_USING_LONGLONG */
{ {
int res; int res;
/* optimized for processor which does not support divide instructions. */ /* optimized for processor which does not support divide instructions. */
#ifdef RT_KPRINTF_USING_LONGLONG #ifdef RT_KPRINTF_USING_LONGLONG
res = (int)(((unsigned long long)*n) % base); res = (int)((*n) % base);
*n = (long long)(((unsigned long long)*n) / base); *n = (long long)((*n) / base);
#else #else
res = (int)(((unsigned long)*n) % base); res = (int)((*n) % base);
*n = (long)(((unsigned long)*n) / base); *n = (long)((*n) / base);
#endif #endif
return res; return res;
@ -727,34 +728,38 @@ rt_inline int skip_atoi(const char **s)
static char *print_number(char *buf, static char *print_number(char *buf,
char *end, char *end,
#ifdef RT_KPRINTF_USING_LONGLONG #ifdef RT_KPRINTF_USING_LONGLONG
long long num, unsigned long long num,
#else #else
long num, unsigned long num,
#endif /* RT_KPRINTF_USING_LONGLONG */ #endif /* RT_KPRINTF_USING_LONGLONG */
int base, int base,
int qualifier,
int s, int s,
#ifdef RT_PRINTF_PRECISION #ifdef RT_PRINTF_PRECISION
int precision, int precision,
#endif /* RT_PRINTF_PRECISION */ #endif /* RT_PRINTF_PRECISION */
int type) int type)
{ {
char c, sign; char c = 0, sign = 0;
#ifdef RT_KPRINTF_USING_LONGLONG #ifdef RT_KPRINTF_USING_LONGLONG
char tmp[64]; char tmp[64] = {0};
#else #else
char tmp[32]; char tmp[32] = {0};
#endif /* RT_KPRINTF_USING_LONGLONG */ #endif /* RT_KPRINTF_USING_LONGLONG */
int precision_bak = precision; int precision_bak = precision;
const char *digits; const char *digits = RT_NULL;
static const char small_digits[] = "0123456789abcdef"; static const char small_digits[] = "0123456789abcdef";
static const char large_digits[] = "0123456789ABCDEF"; static const char large_digits[] = "0123456789ABCDEF";
int i, size; int i = 0;
int size = 0;
size = s; size = s;
digits = (type & LARGE) ? large_digits : small_digits; digits = (type & LARGE) ? large_digits : small_digits;
if (type & LEFT) if (type & LEFT)
{
type &= ~ZEROPAD; type &= ~ZEROPAD;
}
c = (type & ZEROPAD) ? '0' : ' '; c = (type & ZEROPAD) ? '0' : ' ';
@ -762,30 +767,65 @@ static char *print_number(char *buf,
sign = 0; sign = 0;
if (type & SIGN) if (type & SIGN)
{ {
if (num < 0) switch (qualifier)
{
case 'h':
if ((rt_int16_t)num < 0)
{ {
sign = '-'; sign = '-';
num = -num; num = (rt_uint16_t)-num;
} }
else if (type & PLUS) break;
case 'L':
case 'l':
if ((long)num < 0)
{
sign = '-';
num = (unsigned long)-num;
}
break;
case 0:
default:
if ((rt_int32_t)num < 0)
{
sign = '-';
num = (rt_uint32_t)-num;
}
break;
}
if (sign != '-')
{
if (type & PLUS)
{
sign = '+'; sign = '+';
}
else if (type & SPACE) else if (type & SPACE)
{
sign = ' '; sign = ' ';
} }
}
}
#ifdef RT_PRINTF_SPECIAL #ifdef RT_PRINTF_SPECIAL
if (type & SPECIAL) if (type & SPECIAL)
{ {
if (base == 2 || base == 16) if (base == 2 || base == 16)
{
size -= 2; size -= 2;
}
else if (base == 8) else if (base == 8)
{
size--; size--;
} }
}
#endif /* RT_PRINTF_SPECIAL */ #endif /* RT_PRINTF_SPECIAL */
i = 0; i = 0;
if (num == 0) if (num == 0)
{
tmp[i++] = '0'; tmp[i++] = '0';
}
else else
{ {
while (num != 0) while (num != 0)
@ -794,7 +834,9 @@ static char *print_number(char *buf,
#ifdef RT_PRINTF_PRECISION #ifdef RT_PRINTF_PRECISION
if (i > precision) if (i > precision)
{
precision = i; precision = i;
}
size -= precision; size -= precision;
#else #else
size -= i; size -= i;
@ -803,12 +845,17 @@ static char *print_number(char *buf,
if (!(type & (ZEROPAD | LEFT))) if (!(type & (ZEROPAD | LEFT)))
{ {
if ((sign) && (size > 0)) if ((sign) && (size > 0))
{
size--; size--;
}
while (size-- > 0) while (size-- > 0)
{ {
if (buf < end) if (buf < end)
{
*buf = ' '; *buf = ' ';
}
++ buf; ++ buf;
} }
} }
@ -844,7 +891,10 @@ static char *print_number(char *buf,
else if (base == 16) else if (base == 16)
{ {
if (buf < end) if (buf < end)
{
*buf = '0'; *buf = '0';
}
++ buf; ++ buf;
if (buf < end) if (buf < end)
{ {
@ -861,7 +911,10 @@ static char *print_number(char *buf,
while (size-- > 0) while (size-- > 0)
{ {
if (buf < end) if (buf < end)
{
*buf = c; *buf = c;
}
++ buf; ++ buf;
} }
} }
@ -870,7 +923,10 @@ static char *print_number(char *buf,
while (i < precision--) while (i < precision--)
{ {
if (buf < end) if (buf < end)
{
*buf = '0'; *buf = '0';
}
++ buf; ++ buf;
} }
#endif /* RT_PRINTF_PRECISION */ #endif /* RT_PRINTF_PRECISION */
@ -879,14 +935,20 @@ static char *print_number(char *buf,
while (i-- > 0 && (precision_bak != 0)) while (i-- > 0 && (precision_bak != 0))
{ {
if (buf < end) if (buf < end)
{
*buf = tmp[i]; *buf = tmp[i];
}
++ buf; ++ buf;
} }
while (size-- > 0) while (size-- > 0)
{ {
if (buf < end) if (buf < end)
{
*buf = ' '; *buf = ' ';
}
++ buf; ++ buf;
} }
@ -909,21 +971,21 @@ static char *print_number(char *buf,
rt_weak int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list args) rt_weak int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list args)
{ {
#ifdef RT_KPRINTF_USING_LONGLONG #ifdef RT_KPRINTF_USING_LONGLONG
unsigned long long num; unsigned long long num = 0;
#else #else
rt_uint32_t num; unsigned long num = 0;
#endif /* RT_KPRINTF_USING_LONGLONG */ #endif /* RT_KPRINTF_USING_LONGLONG */
int i, len; int i = 0, len = 0;
char *str, *end, c; char *str = RT_NULL, *end = RT_NULL, c = 0;
const char *s; const char *s = RT_NULL;
rt_uint8_t base; /* the base of number */ rt_uint8_t base = 0; /* the base of number */
rt_uint8_t flags; /* flags to print number */ rt_uint8_t flags = 0; /* flags to print number */
rt_uint8_t qualifier; /* 'h', 'l', or 'L' for integer fields */ rt_uint8_t qualifier = 0; /* 'h', 'l', or 'L' for integer fields */
rt_int32_t field_width; /* width of output field */ rt_int32_t field_width = 0; /* width of output field */
#ifdef RT_PRINTF_PRECISION #ifdef RT_PRINTF_PRECISION
int precision; /* min. # of digits for integers and max for a string */ int precision = 0; /* min. # of digits for integers and max for a string */
#endif /* RT_PRINTF_PRECISION */ #endif /* RT_PRINTF_PRECISION */
str = buf; str = buf;
@ -941,7 +1003,10 @@ rt_weak int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list arg
if (*fmt != '%') if (*fmt != '%')
{ {
if (str < end) if (str < end)
{
*str = *fmt; *str = *fmt;
}
++ str; ++ str;
continue; continue;
} }
@ -963,7 +1028,10 @@ rt_weak int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list arg
/* get field width */ /* get field width */
field_width = -1; field_width = -1;
if (_ISDIGIT(*fmt)) field_width = skip_atoi(&fmt); if (_ISDIGIT(*fmt))
{
field_width = skip_atoi(&fmt);
}
else if (*fmt == '*') else if (*fmt == '*')
{ {
++ fmt; ++ fmt;
@ -982,14 +1050,20 @@ rt_weak int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list arg
if (*fmt == '.') if (*fmt == '.')
{ {
++ fmt; ++ fmt;
if (_ISDIGIT(*fmt)) precision = skip_atoi(&fmt); if (_ISDIGIT(*fmt))
{
precision = skip_atoi(&fmt);
}
else if (*fmt == '*') else if (*fmt == '*')
{ {
++ fmt; ++ fmt;
/* it's the next argument */ /* it's the next argument */
precision = va_arg(args, int); precision = va_arg(args, int);
} }
if (precision < 0) precision = 0; if (precision < 0)
{
precision = 0;
}
} }
#endif /* RT_PRINTF_PRECISION */ #endif /* RT_PRINTF_PRECISION */
/* get the conversion qualifier */ /* get the conversion qualifier */
@ -1028,7 +1102,10 @@ rt_weak int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list arg
/* get character */ /* get character */
c = (rt_uint8_t)va_arg(args, int); c = (rt_uint8_t)va_arg(args, int);
if (str < end) *str = c; if (str < end)
{
*str = c;
}
++ str; ++ str;
/* put width */ /* put width */
@ -1041,11 +1118,17 @@ rt_weak int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list arg
case 's': case 's':
s = va_arg(args, char *); s = va_arg(args, char *);
if (!s) s = "(NULL)"; if (!s)
{
s = "(NULL)";
}
for (len = 0; (len != field_width) && (s[len] != '\0'); len++); for (len = 0; (len != field_width) && (s[len] != '\0'); len++);
#ifdef RT_PRINTF_PRECISION #ifdef RT_PRINTF_PRECISION
if (precision > 0 && len > precision) len = precision; if (precision > 0 && len > precision)
{
len = precision;
}
#endif /* RT_PRINTF_PRECISION */ #endif /* RT_PRINTF_PRECISION */
if (!(flags & LEFT)) if (!(flags & LEFT))
@ -1075,21 +1158,28 @@ rt_weak int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list arg
if (field_width == -1) if (field_width == -1)
{ {
field_width = sizeof(void *) << 1; field_width = sizeof(void *) << 1;
#ifdef RT_PRINTF_SPECIAL
field_width += 2; /* `0x` prefix */
flags |= SPECIAL;
#endif
flags |= ZEROPAD; flags |= ZEROPAD;
} }
#ifdef RT_PRINTF_PRECISION #ifdef RT_PRINTF_PRECISION
str = print_number(str, end, str = print_number(str, end,
(long)va_arg(args, void *), (unsigned long)va_arg(args, void *),
16, field_width, precision, flags); 16, qualifier, field_width, precision, flags);
#else #else
str = print_number(str, end, str = print_number(str, end,
(long)va_arg(args, void *), (unsigned long)va_arg(args, void *),
16, field_width, flags); 16, qualifier, field_width, flags);
#endif /* RT_PRINTF_PRECISION */ #endif
continue; continue;
case '%': case '%':
if (str < end) *str = '%'; if (str < end)
{
*str = '%';
}
++ str; ++ str;
continue; continue;
@ -1114,12 +1204,18 @@ rt_weak int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list arg
break; break;
default: default:
if (str < end) *str = '%'; if (str < end)
{
*str = '%';
}
++ str; ++ str;
if (*fmt) if (*fmt)
{ {
if (str < end) *str = *fmt; if (str < end)
{
*str = *fmt;
}
++ str; ++ str;
} }
else else
@ -1130,35 +1226,42 @@ rt_weak int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list arg
} }
#ifdef RT_KPRINTF_USING_LONGLONG #ifdef RT_KPRINTF_USING_LONGLONG
if (qualifier == 'L') num = va_arg(args, long long); if (qualifier == 'L')
{
num = va_arg(args, unsigned long long);
}
else if (qualifier == 'l') else if (qualifier == 'l')
#else #else
if (qualifier == 'l') if (qualifier == 'l')
#endif /* RT_KPRINTF_USING_LONGLONG */ #endif /* RT_KPRINTF_USING_LONGLONG */
{ {
num = va_arg(args, rt_uint32_t); num = va_arg(args, unsigned long);
if (flags & SIGN) num = (rt_int32_t)num;
} }
else if (qualifier == 'h') else if (qualifier == 'h')
{ {
num = (rt_uint16_t)va_arg(args, int); num = (rt_uint16_t)va_arg(args, rt_int32_t);
if (flags & SIGN) num = (rt_int16_t)num; if (flags & SIGN)
{
num = (rt_int16_t)num;
}
} }
else else
{ {
num = va_arg(args, rt_uint32_t); num = (rt_uint32_t)va_arg(args, unsigned long);
if (flags & SIGN) num = (rt_int32_t)num;
} }
#ifdef RT_PRINTF_PRECISION #ifdef RT_PRINTF_PRECISION
str = print_number(str, end, num, base, field_width, precision, flags); str = print_number(str, end, num, base, qualifier, field_width, precision, flags);
#else #else
str = print_number(str, end, num, base, field_width, flags); str = print_number(str, end, num, base, qualifier, field_width, flags);
#endif /* RT_PRINTF_PRECISION */ #endif
} }
if (size > 0) if (size > 0)
{ {
if (str < end) *str = '\0'; if (str < end)
{
*str = '\0';
}
else else
{ {
end[-1] = '\0'; end[-1] = '\0';
@ -1185,7 +1288,7 @@ RTM_EXPORT(rt_vsnprintf);
*/ */
int rt_snprintf(char *buf, rt_size_t size, const char *fmt, ...) int rt_snprintf(char *buf, rt_size_t size, const char *fmt, ...)
{ {
rt_int32_t n; rt_int32_t n = 0;
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
@ -1224,7 +1327,7 @@ RTM_EXPORT(rt_vsprintf);
*/ */
int rt_sprintf(char *buf, const char *format, ...) int rt_sprintf(char *buf, const char *format, ...)
{ {
rt_int32_t n; rt_int32_t n = 0;
va_list arg_ptr; va_list arg_ptr;
va_start(arg_ptr, format); va_start(arg_ptr, format);
@ -1325,7 +1428,10 @@ RTM_EXPORT(rt_hw_console_output);
*/ */
void rt_kputs(const char *str) void rt_kputs(const char *str)
{ {
if (!str) return; if (!str)
{
return;
}
#ifdef RT_USING_DEVICE #ifdef RT_USING_DEVICE
if (_console_device == RT_NULL) if (_console_device == RT_NULL)
@ -1351,7 +1457,7 @@ void rt_kputs(const char *str)
rt_weak int rt_kprintf(const char *fmt, ...) rt_weak int rt_kprintf(const char *fmt, ...)
{ {
va_list args; va_list args;
rt_size_t length; rt_size_t length = 0;
static char rt_log_buf[RT_CONSOLEBUF_SIZE]; static char rt_log_buf[RT_CONSOLEBUF_SIZE];
va_start(args, fmt); va_start(args, fmt);
@ -1362,7 +1468,10 @@ rt_weak int rt_kprintf(const char *fmt, ...)
* length. */ * length. */
length = rt_vsnprintf(rt_log_buf, sizeof(rt_log_buf) - 1, fmt, args); length = rt_vsnprintf(rt_log_buf, sizeof(rt_log_buf) - 1, fmt, args);
if (length > RT_CONSOLEBUF_SIZE - 1) if (length > RT_CONSOLEBUF_SIZE - 1)
{
length = RT_CONSOLEBUF_SIZE - 1; length = RT_CONSOLEBUF_SIZE - 1;
}
#ifdef RT_USING_DEVICE #ifdef RT_USING_DEVICE
if (_console_device == RT_NULL) if (_console_device == RT_NULL)
{ {
@ -1708,10 +1817,10 @@ void rt_page_free(void *addr, rt_size_t npages)
*/ */
rt_weak void *rt_malloc_align(rt_size_t size, rt_size_t align) rt_weak void *rt_malloc_align(rt_size_t size, rt_size_t align)
{ {
void *ptr; void *ptr = RT_NULL;
void *align_ptr; void *align_ptr = RT_NULL;
int uintptr_size; int uintptr_size = 0;
rt_size_t align_size; rt_size_t align_size = 0;
/* sizeof pointer */ /* sizeof pointer */
uintptr_size = sizeof(void*); uintptr_size = sizeof(void*);
@ -1822,16 +1931,25 @@ const rt_uint8_t __lowest_bit_bitmap[] =
*/ */
int __rt_ffs(int value) int __rt_ffs(int value)
{ {
if (value == 0) return 0; if (value == 0)
{
return 0;
}
if (value & 0xff) if (value & 0xff)
{
return __lowest_bit_bitmap[value & 0xff] + 1; return __lowest_bit_bitmap[value & 0xff] + 1;
}
if (value & 0xff00) if (value & 0xff00)
{
return __lowest_bit_bitmap[(value & 0xff00) >> 8] + 9; return __lowest_bit_bitmap[(value & 0xff00) >> 8] + 9;
}
if (value & 0xff0000) if (value & 0xff0000)
{
return __lowest_bit_bitmap[(value & 0xff0000) >> 16] + 17; return __lowest_bit_bitmap[(value & 0xff0000) >> 16] + 17;
}
return __lowest_bit_bitmap[(value & 0xff000000) >> 24] + 25; return __lowest_bit_bitmap[(value & 0xff000000) >> 24] + 25;
} }