X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=lib%2Ftiny-printf.c;h=30ac7596d343716f0041619e73e46e0359328126;hb=76f1f38816d8763b51e5f1d6ca099a88aa1fd077;hp=6766a8f1c8b648a201f430b15116dbf69c8a096e;hpb=a5ecdd08fdf647c7c5a97e937ebed2d97549352f;p=u-boot diff --git a/lib/tiny-printf.c b/lib/tiny-printf.c index 6766a8f1c8..30ac7596d3 100644 --- a/lib/tiny-printf.c +++ b/lib/tiny-printf.c @@ -13,21 +13,33 @@ #include #include -static char *bf; -static char zs; +struct printf_info { + char *bf; /* Digit buffer */ + char zs; /* non-zero if a digit has been written */ + char *outstr; /* Next output position for sprintf() */ -static void out(char c) + /* Output a character */ + void (*putc)(struct printf_info *info, char ch); +}; + +void putc_normal(struct printf_info *info, char ch) +{ + putc(ch); +} + +static void out(struct printf_info *info, char c) { - *bf++ = c; + *info->bf++ = c; } -static void out_dgt(char dgt) +static void out_dgt(struct printf_info *info, char dgt) { - out(dgt + (dgt < 10 ? '0' : 'a' - 10)); - zs = 1; + out(info, dgt + (dgt < 10 ? '0' : 'a' - 10)); + info->zs = 1; } -static void div_out(unsigned int *num, unsigned int div) +static void div_out(struct printf_info *info, unsigned int *num, + unsigned int div) { unsigned char dgt = 0; @@ -36,27 +48,24 @@ static void div_out(unsigned int *num, unsigned int div) dgt++; } - if (zs || dgt > 0) - out_dgt(dgt); + if (info->zs || dgt > 0) + out_dgt(info, dgt); } -int printf(const char *fmt, ...) +int _vprintf(struct printf_info *info, const char *fmt, va_list va) { - va_list va; char ch; char *p; unsigned int num; char buf[12]; unsigned int div; - va_start(va, fmt); - while ((ch = *(fmt++))) { if (ch != '%') { - putc(ch); + info->putc(info, ch); } else { - char lz = 0; - char w = 0; + bool lz = false; + int width = 0; ch = *(fmt++); if (ch == '0') { @@ -65,58 +74,137 @@ int printf(const char *fmt, ...) } if (ch >= '0' && ch <= '9') { - w = 0; + width = 0; while (ch >= '0' && ch <= '9') { - w = (w * 10) + ch - '0'; + width = (width * 10) + ch - '0'; ch = *fmt++; } } - bf = buf; - p = bf; - zs = 0; + info->bf = buf; + p = info->bf; + info->zs = 0; switch (ch) { - case 0: + case '\0': goto abort; case 'u': case 'd': num = va_arg(va, unsigned int); if (ch == 'd' && (int)num < 0) { num = -(int)num; - out('-'); + out(info, '-'); + } + if (!num) { + out_dgt(info, 0); + } else { + for (div = 1000000000; div; div /= 10) + div_out(info, &num, div); } - for (div = 1000000000; div; div /= 10) - div_out(&num, div); break; case 'x': num = va_arg(va, unsigned int); - for (div = 0x10000000; div; div /= 0x10) - div_out(&num, div); + if (!num) { + out_dgt(info, 0); + } else { + for (div = 0x10000000; div; div /= 0x10) + div_out(info, &num, div); + } break; case 'c': - out((char)(va_arg(va, int))); + out(info, (char)(va_arg(va, int))); break; case 's': p = va_arg(va, char*); break; case '%': - out('%'); + out(info, '%'); default: break; } - *bf = 0; - bf = p; - while (*bf++ && w > 0) - w--; - while (w-- > 0) - putc(lz ? '0' : ' '); - while ((ch = *p++)) - putc(ch); + *info->bf = 0; + info->bf = p; + while (*info->bf++ && width > 0) + width--; + while (width-- > 0) + info->putc(info, lz ? '0' : ' '); + if (p) { + while ((ch = *p++)) + info->putc(info, ch); + } } } abort: - va_end(va); return 0; } + +int vprintf(const char *fmt, va_list va) +{ + struct printf_info info; + + info.putc = putc_normal; + return _vprintf(&info, fmt, va); +} + +int printf(const char *fmt, ...) +{ + struct printf_info info; + + va_list va; + int ret; + + info.putc = putc_normal; + va_start(va, fmt); + ret = _vprintf(&info, fmt, va); + va_end(va); + + return ret; +} + +static void putc_outstr(struct printf_info *info, char ch) +{ + *info->outstr++ = ch; +} + +int sprintf(char *buf, const char *fmt, ...) +{ + struct printf_info info; + va_list va; + int ret; + + va_start(va, fmt); + info.outstr = buf; + info.putc = putc_outstr; + ret = _vprintf(&info, fmt, va); + va_end(va); + *info.outstr = '\0'; + + return ret; +} + +/* Note that size is ignored */ +int snprintf(char *buf, size_t size, const char *fmt, ...) +{ + struct printf_info info; + va_list va; + int ret; + + va_start(va, fmt); + info.outstr = buf; + info.putc = putc_outstr; + ret = _vprintf(&info, fmt, va); + va_end(va); + *info.outstr = '\0'; + + return ret; +} + +void __assert_fail(const char *assertion, const char *file, unsigned line, + const char *function) +{ + /* This will not return */ + printf("%s:%u: %s: Assertion `%s' failed.", file, line, function, + assertion); + hang(); +}