X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=lib%2Fvsprintf.c;h=4c82837cc41e8e55899d945e8f27d399a0b0be71;hb=baaaa7539c7511e7e90453ecf0f20d8eaeeb70c6;hp=92a9232c2a1421fd3033f9248d23749cce9d07b0;hpb=8acdae681a61d05ef2d93b3c51a20a5257afb610;p=u-boot diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 92a9232c2a..4c82837cc4 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -23,23 +23,8 @@ #endif #include -# define NUM_TYPE long long #define noinline __attribute__((noinline)) -/* some reluctance to put this into a new limits.h, so it is here */ -#define INT_MAX ((int)(~0U>>1)) - -const char hex_asc[] = "0123456789abcdef"; -#define hex_asc_lo(x) hex_asc[((x) & 0x0f)] -#define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4] - -static inline char *pack_hex_byte(char *buf, u8 byte) -{ - *buf++ = hex_asc_hi(byte); - *buf++ = hex_asc_lo(byte); - return buf; -} - unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base) { @@ -104,7 +89,7 @@ long simple_strtol(const char *cp, char **endp, unsigned int base) return simple_strtoul(cp, endp, base); } -int ustrtoul(const char *cp, char **endp, unsigned int base) +unsigned long ustrtoul(const char *cp, char **endp, unsigned int base) { unsigned long result = simple_strtoul(cp, endp, base); switch (**endp) { @@ -127,6 +112,29 @@ int ustrtoul(const char *cp, char **endp, unsigned int base) return result; } +unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base) +{ + unsigned long long result = simple_strtoull(cp, endp, base); + switch (**endp) { + case 'G': + result *= 1024; + /* fall through */ + case 'M': + result *= 1024; + /* fall through */ + case 'K': + case 'k': + result *= 1024; + if ((*endp)[1] == 'i') { + if ((*endp)[2] == 'B') + (*endp) += 3; + else + (*endp) += 2; + } + } + return result; +} + unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base) { @@ -158,6 +166,25 @@ unsigned long long simple_strtoull(const char *cp, char **endp, return result; } +long trailing_strtoln(const char *str, const char *end) +{ + const char *p; + + if (!end) + end = str + strlen(str); + for (p = end - 1; p > str; p--) { + if (!isdigit(*p)) + return simple_strtoul(p + 1, NULL, 10); + } + + return -1; +} + +long trailing_strtol(const char *str) +{ + return trailing_strtoln(str, NULL); +} + /* we use this so that we can do without the ctype library */ #define is_digit(c) ((c) >= '0' && (c) <= '9') @@ -259,7 +286,7 @@ static char *put_dec_full(char *buf, unsigned q) return buf; } /* No inlining helps gcc to use registers better */ -static noinline char *put_dec(char *buf, unsigned NUM_TYPE num) +static noinline char *put_dec(char *buf, uint64_t num) { while (1) { unsigned rem; @@ -292,7 +319,7 @@ static noinline char *put_dec(char *buf, unsigned NUM_TYPE num) #define ADDCH(str, ch) (*(str)++ = (ch)) #endif -static char *number(char *buf, char *end, unsigned NUM_TYPE num, +static char *number(char *buf, char *end, u64 num, int base, int size, int precision, int type) { /* we are called with base 8, 10 or 16, only, thus don't need "G..." */ @@ -311,9 +338,9 @@ static char *number(char *buf, char *end, unsigned NUM_TYPE num, type &= ~ZEROPAD; sign = 0; if (type & SIGN) { - if ((signed NUM_TYPE) num < 0) { + if ((s64) num < 0) { sign = '-'; - num = -(signed NUM_TYPE) num; + num = -(s64) num; size--; } else if (type & PLUS) { sign = '+'; @@ -396,7 +423,7 @@ static char *string(char *buf, char *end, char *s, int field_width, { int len, i; - if (s == 0) + if (s == NULL) s = ""; len = strnlen(s, precision); @@ -412,6 +439,17 @@ static char *string(char *buf, char *end, char *s, int field_width, } #ifdef CONFIG_CMD_NET +static const char hex_asc[] = "0123456789abcdef"; +#define hex_asc_lo(x) hex_asc[((x) & 0x0f)] +#define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4] + +static inline char *pack_hex_byte(char *buf, u8 byte) +{ + *buf++ = hex_asc_hi(byte); + *buf++ = hex_asc_lo(byte); + return buf; +} + static char *mac_address_string(char *buf, char *end, u8 *addr, int field_width, int precision, int flags) { @@ -496,12 +534,31 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width, static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field_width, int precision, int flags) { + u64 num = (uintptr_t)ptr; + + /* + * Being a boot loader, we explicitly allow pointers to + * (physical) address null. + */ +#if 0 if (!ptr) return string(buf, end, "(null)", field_width, precision, flags); +#endif #ifdef CONFIG_CMD_NET switch (*fmt) { + case 'a': + flags |= SPECIAL | ZEROPAD; + + switch (fmt[1]) { + case 'p': + default: + field_width = sizeof(phys_addr_t) * 2 + 2; + num = *(phys_addr_t *)ptr; + break; + } + break; case 'm': flags |= SPECIAL; /* Fallthrough */ @@ -527,14 +584,13 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, field_width = 2*sizeof(void *); flags |= ZEROPAD; } - return number(buf, end, (unsigned long)ptr, 16, field_width, - precision, flags); + return number(buf, end, num, 16, field_width, precision, flags); } static int vsnprintf_internal(char *buf, size_t size, const char *fmt, va_list args) { - unsigned NUM_TYPE num; + u64 num; int base; char *str; @@ -722,6 +778,7 @@ repeat: ADDCH(str, '\0'); if (str > end) end[-1] = '\0'; + --str; } #else *str = '\0'; @@ -804,13 +861,11 @@ int sprintf(char *buf, const char *fmt, ...) return i; } -void panic(const char *fmt, ...) +static void panic_finish(void) __attribute__ ((noreturn)); + +static void panic_finish(void) { - va_list args; - va_start(args, fmt); - vprintf(fmt, args); putc('\n'); - va_end(args); #if defined(CONFIG_PANIC_HANG) hang(); #else @@ -821,6 +876,21 @@ void panic(const char *fmt, ...) ; } +void panic_str(const char *str) +{ + puts(str); + panic_finish(); +} + +void panic(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + panic_finish(); +} + void __assert_fail(const char *assertion, const char *file, unsigned line, const char *function) { @@ -842,3 +912,35 @@ char *simple_itoa(ulong i) } while (i > 0); return p + 1; } + +/* We don't seem to have %'d in U-Boot */ +void print_grouped_ull(unsigned long long int_val, int digits) +{ + char str[21], *s; + int grab = 3; + + digits = (digits + 2) / 3; + sprintf(str, "%*llu", digits * 3, int_val); + for (s = str; *s; s += grab) { + if (s != str) + putc(s[-1] != ' ' ? ',' : ' '); + printf("%.*s", grab, s); + grab = 3; + } +} + +bool str2off(const char *p, loff_t *num) +{ + char *endptr; + + *num = simple_strtoull(p, &endptr, 16); + return *p != '\0' && *endptr == '\0'; +} + +bool str2long(const char *p, ulong *num) +{ + char *endptr; + + *num = simple_strtoul(p, &endptr, 16); + return *p != '\0' && *endptr == '\0'; +}