X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=lib%2Fvsprintf.c;h=874a2951f7053ef395cfee8ffe78464eee855039;hb=555a347209000f8655ca637a5a04f7275a2fb999;hp=b7a79c0e0c90ea6a5bd275a4bdf0fd3853c5d610;hpb=0eb257683ded98431d6c30b360b7bd37235f518d;p=u-boot diff --git a/lib/vsprintf.c b/lib/vsprintf.c index b7a79c0e0c..874a2951f7 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -15,148 +15,12 @@ #include #include #include -#include #include -#if !defined(CONFIG_PANIC_HANG) -#include -#endif #include #define noinline __attribute__((noinline)) -/* some reluctance to put this into a new limits.h, so it is here */ -#define INT_MAX ((int)(~0U>>1)) - -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; -} - -unsigned long simple_strtoul(const char *cp, char **endp, - unsigned int base) -{ - unsigned long result = 0; - unsigned long value; - - if (*cp == '0') { - cp++; - if ((*cp == 'x') && isxdigit(cp[1])) { - base = 16; - cp++; - } - - if (!base) - base = 8; - } - - if (!base) - base = 10; - - while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) - ? toupper(*cp) : *cp)-'A'+10) < base) { - result = result*base + value; - cp++; - } - - if (endp) - *endp = (char *)cp; - - return result; -} - -int strict_strtoul(const char *cp, unsigned int base, unsigned long *res) -{ - char *tail; - unsigned long val; - size_t len; - - *res = 0; - len = strlen(cp); - if (len == 0) - return -EINVAL; - - val = simple_strtoul(cp, &tail, base); - if (tail == cp) - return -EINVAL; - - if ((*tail == '\0') || - ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) { - *res = val; - return 0; - } - - return -EINVAL; -} - -long simple_strtol(const char *cp, char **endp, unsigned int base) -{ - if (*cp == '-') - return -simple_strtoul(cp + 1, endp, base); - - return simple_strtoul(cp, endp, base); -} - -int ustrtoul(const char *cp, char **endp, unsigned int base) -{ - unsigned long result = simple_strtoul(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) -{ - unsigned long long result = 0, value; - - if (*cp == '0') { - cp++; - if ((*cp == 'x') && isxdigit(cp[1])) { - base = 16; - cp++; - } - - if (!base) - base = 8; - } - - if (!base) - base = 10; - - while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0' - : (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) { - result = result * base + value; - cp++; - } - - if (endp) - *endp = (char *) cp; - - return result; -} - /* we use this so that we can do without the ctype library */ #define is_digit(c) ((c) >= '0' && (c) <= '9') @@ -258,7 +122,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, u64 num) +static noinline char *put_dec(char *buf, uint64_t num) { while (1) { unsigned rem; @@ -277,7 +141,6 @@ static noinline char *put_dec(char *buf, u64 num) #define SMALL 32 /* Must be 32 == 0x20 */ #define SPECIAL 64 /* 0x */ -#ifdef CONFIG_SYS_VSNPRINTF /* * Macro to add a new character to our output string, but only if it will * fit. The macro moves to the next character position in the output string. @@ -287,9 +150,6 @@ static noinline char *put_dec(char *buf, u64 num) *(str) = (ch); \ ++str; \ } while (0) -#else -#define ADDCH(str, ch) (*(str)++ = (ch)) -#endif static char *number(char *buf, char *end, u64 num, int base, int size, int precision, int type) @@ -411,6 +271,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) { @@ -495,6 +366,8 @@ 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. @@ -507,6 +380,17 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, #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 */ @@ -532,8 +416,7 @@ 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, @@ -554,13 +437,11 @@ static int vsnprintf_internal(char *buf, size_t size, const char *fmt, /* 't' added for ptrdiff_t */ char *end = buf + size; -#ifdef CONFIG_SYS_VSNPRINTF /* Make sure end is always >= buf - do we want this in U-Boot? */ if (end < buf) { end = ((void *)-1); size = end - buf; } -#endif str = buf; for (; *fmt ; ++fmt) { @@ -722,20 +603,16 @@ repeat: flags); } -#ifdef CONFIG_SYS_VSNPRINTF if (size > 0) { ADDCH(str, '\0'); if (str > end) end[-1] = '\0'; + --str; } -#else - *str = '\0'; -#endif /* the trailing null byte doesn't count towards the total */ return str - buf; } -#ifdef CONFIG_SYS_VSNPRINTF int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) { @@ -778,7 +655,6 @@ int scnprintf(char *buf, size_t size, const char *fmt, ...) return i; } -#endif /* CONFIG_SYS_VSNPRINT */ /** * Format a string and place it in a buffer (va_list version) @@ -809,23 +685,43 @@ int sprintf(char *buf, const char *fmt, ...) return i; } -void panic(const char *fmt, ...) +int printf(const char *fmt, ...) { va_list args; + uint i; + char printbuffer[CONFIG_SYS_PBSIZE]; + va_start(args, fmt); - vprintf(fmt, args); - putc('\n'); + + /* + * For this to work, printbuffer must be larger than + * anything we ever want to print. + */ + i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); va_end(args); -#if defined(CONFIG_PANIC_HANG) - hang(); -#else - udelay(100000); /* allow messages to go out */ - do_reset(NULL, 0, 0, NULL); -#endif - while (1) - ; + + /* Print the string */ + puts(printbuffer); + return i; +} + +int vprintf(const char *fmt, va_list args) +{ + uint i; + char printbuffer[CONFIG_SYS_PBSIZE]; + + /* + * For this to work, printbuffer must be larger than + * anything we ever want to print. + */ + i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); + + /* Print the string */ + puts(printbuffer); + return i; } + void __assert_fail(const char *assertion, const char *file, unsigned line, const char *function) { @@ -847,3 +743,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'; +}