17d9cde10SStefan Roese /* 27d9cde10SStefan Roese * Tiny printf version for SPL 37d9cde10SStefan Roese * 47d9cde10SStefan Roese * Copied from: 57d9cde10SStefan Roese * http://www.sparetimelabs.com/printfrevisited/printfrevisited.php 67d9cde10SStefan Roese * 77d9cde10SStefan Roese * Copyright (C) 2004,2008 Kustaa Nyholm 87d9cde10SStefan Roese * 97d9cde10SStefan Roese * SPDX-License-Identifier: LGPL-2.1+ 107d9cde10SStefan Roese */ 117d9cde10SStefan Roese 127d9cde10SStefan Roese #include <common.h> 137d9cde10SStefan Roese #include <stdarg.h> 147d9cde10SStefan Roese #include <serial.h> 157d9cde10SStefan Roese 16*45313e83SSimon Glass struct printf_info { 17*45313e83SSimon Glass char *bf; /* Digit buffer */ 18*45313e83SSimon Glass char zs; /* non-zero if a digit has been written */ 19*45313e83SSimon Glass char *outstr; /* Next output position for sprintf() */ 207d9cde10SStefan Roese 21*45313e83SSimon Glass /* Output a character */ 22*45313e83SSimon Glass void (*putc)(struct printf_info *info, char ch); 23*45313e83SSimon Glass }; 245c411d88SSimon Glass 25*45313e83SSimon Glass void putc_normal(struct printf_info *info, char ch) 267d9cde10SStefan Roese { 27*45313e83SSimon Glass putc(ch); 287d9cde10SStefan Roese } 297d9cde10SStefan Roese 30*45313e83SSimon Glass static void out(struct printf_info *info, char c) 317d9cde10SStefan Roese { 32*45313e83SSimon Glass *info->bf++ = c; 337d9cde10SStefan Roese } 347d9cde10SStefan Roese 35*45313e83SSimon Glass static void out_dgt(struct printf_info *info, char dgt) 36*45313e83SSimon Glass { 37*45313e83SSimon Glass out(info, dgt + (dgt < 10 ? '0' : 'a' - 10)); 38*45313e83SSimon Glass info->zs = 1; 39*45313e83SSimon Glass } 40*45313e83SSimon Glass 41*45313e83SSimon Glass static void div_out(struct printf_info *info, unsigned int *num, 42*45313e83SSimon Glass unsigned int div) 437d9cde10SStefan Roese { 447d9cde10SStefan Roese unsigned char dgt = 0; 457d9cde10SStefan Roese 46a5ecdd08SStefan Roese while (*num >= div) { 47a5ecdd08SStefan Roese *num -= div; 487d9cde10SStefan Roese dgt++; 497d9cde10SStefan Roese } 507d9cde10SStefan Roese 51*45313e83SSimon Glass if (info->zs || dgt > 0) 52*45313e83SSimon Glass out_dgt(info, dgt); 537d9cde10SStefan Roese } 547d9cde10SStefan Roese 55*45313e83SSimon Glass int _vprintf(struct printf_info *info, const char *fmt, va_list va) 567d9cde10SStefan Roese { 577d9cde10SStefan Roese char ch; 587d9cde10SStefan Roese char *p; 59a5ecdd08SStefan Roese unsigned int num; 60a5ecdd08SStefan Roese char buf[12]; 61a5ecdd08SStefan Roese unsigned int div; 627d9cde10SStefan Roese 637d9cde10SStefan Roese while ((ch = *(fmt++))) { 647d9cde10SStefan Roese if (ch != '%') { 65*45313e83SSimon Glass info->putc(info, ch); 667d9cde10SStefan Roese } else { 671fb67608SSimon Glass bool lz = false; 681fb67608SSimon Glass int width = 0; 697d9cde10SStefan Roese 707d9cde10SStefan Roese ch = *(fmt++); 717d9cde10SStefan Roese if (ch == '0') { 727d9cde10SStefan Roese ch = *(fmt++); 737d9cde10SStefan Roese lz = 1; 747d9cde10SStefan Roese } 757d9cde10SStefan Roese 767d9cde10SStefan Roese if (ch >= '0' && ch <= '9') { 771fb67608SSimon Glass width = 0; 787d9cde10SStefan Roese while (ch >= '0' && ch <= '9') { 791fb67608SSimon Glass width = (width * 10) + ch - '0'; 807d9cde10SStefan Roese ch = *fmt++; 817d9cde10SStefan Roese } 827d9cde10SStefan Roese } 83*45313e83SSimon Glass info->bf = buf; 84*45313e83SSimon Glass p = info->bf; 85*45313e83SSimon Glass info->zs = 0; 867d9cde10SStefan Roese 877d9cde10SStefan Roese switch (ch) { 881fb67608SSimon Glass case '\0': 897d9cde10SStefan Roese goto abort; 907d9cde10SStefan Roese case 'u': 917d9cde10SStefan Roese case 'd': 927d9cde10SStefan Roese num = va_arg(va, unsigned int); 937d9cde10SStefan Roese if (ch == 'd' && (int)num < 0) { 947d9cde10SStefan Roese num = -(int)num; 95*45313e83SSimon Glass out(info, '-'); 967d9cde10SStefan Roese } 9774b1320aSSimon Glass if (!num) { 98*45313e83SSimon Glass out_dgt(info, 0); 9974b1320aSSimon Glass } else { 100a5ecdd08SStefan Roese for (div = 1000000000; div; div /= 10) 101*45313e83SSimon Glass div_out(info, &num, div); 10274b1320aSSimon Glass } 1037d9cde10SStefan Roese break; 1047d9cde10SStefan Roese case 'x': 1057d9cde10SStefan Roese num = va_arg(va, unsigned int); 10674b1320aSSimon Glass if (!num) { 107*45313e83SSimon Glass out_dgt(info, 0); 10874b1320aSSimon Glass } else { 109a5ecdd08SStefan Roese for (div = 0x10000000; div; div /= 0x10) 110*45313e83SSimon Glass div_out(info, &num, div); 11174b1320aSSimon Glass } 1127d9cde10SStefan Roese break; 1137d9cde10SStefan Roese case 'c': 114*45313e83SSimon Glass out(info, (char)(va_arg(va, int))); 1157d9cde10SStefan Roese break; 1167d9cde10SStefan Roese case 's': 1177d9cde10SStefan Roese p = va_arg(va, char*); 1187d9cde10SStefan Roese break; 1197d9cde10SStefan Roese case '%': 120*45313e83SSimon Glass out(info, '%'); 1217d9cde10SStefan Roese default: 1227d9cde10SStefan Roese break; 1237d9cde10SStefan Roese } 1247d9cde10SStefan Roese 125*45313e83SSimon Glass *info->bf = 0; 126*45313e83SSimon Glass info->bf = p; 127*45313e83SSimon Glass while (*info->bf++ && width > 0) 1281fb67608SSimon Glass width--; 1291fb67608SSimon Glass while (width-- > 0) 130*45313e83SSimon Glass info->putc(info, lz ? '0' : ' '); 1318e31681cSSimon Glass if (p) { 1327d9cde10SStefan Roese while ((ch = *p++)) 133*45313e83SSimon Glass info->putc(info, ch); 1347d9cde10SStefan Roese } 1357d9cde10SStefan Roese } 1368e31681cSSimon Glass } 1377d9cde10SStefan Roese 1387d9cde10SStefan Roese abort: 1397d9cde10SStefan Roese return 0; 1407d9cde10SStefan Roese } 141962a43ccSSjoerd Simons 142da70b4d1SHans de Goede int vprintf(const char *fmt, va_list va) 143da70b4d1SHans de Goede { 144*45313e83SSimon Glass struct printf_info info; 145*45313e83SSimon Glass 146*45313e83SSimon Glass info.putc = putc_normal; 147*45313e83SSimon Glass return _vprintf(&info, fmt, va); 148da70b4d1SHans de Goede } 149da70b4d1SHans de Goede 150962a43ccSSjoerd Simons int printf(const char *fmt, ...) 151962a43ccSSjoerd Simons { 152*45313e83SSimon Glass struct printf_info info; 153*45313e83SSimon Glass 154962a43ccSSjoerd Simons va_list va; 155962a43ccSSjoerd Simons int ret; 156962a43ccSSjoerd Simons 157*45313e83SSimon Glass info.putc = putc_normal; 158962a43ccSSjoerd Simons va_start(va, fmt); 159*45313e83SSimon Glass ret = _vprintf(&info, fmt, va); 160962a43ccSSjoerd Simons va_end(va); 161962a43ccSSjoerd Simons 162962a43ccSSjoerd Simons return ret; 163962a43ccSSjoerd Simons } 1645c411d88SSimon Glass 165*45313e83SSimon Glass static void putc_outstr(struct printf_info *info, char ch) 1665c411d88SSimon Glass { 167*45313e83SSimon Glass *info->outstr++ = ch; 1685c411d88SSimon Glass } 1695c411d88SSimon Glass 170abeb272dSMarek Vasut int sprintf(char *buf, const char *fmt, ...) 1715c411d88SSimon Glass { 172*45313e83SSimon Glass struct printf_info info; 1735c411d88SSimon Glass va_list va; 1745c411d88SSimon Glass int ret; 1755c411d88SSimon Glass 1765c411d88SSimon Glass va_start(va, fmt); 177*45313e83SSimon Glass info.outstr = buf; 178*45313e83SSimon Glass info.putc = putc_outstr; 179*45313e83SSimon Glass ret = _vprintf(&info, fmt, va); 1805c411d88SSimon Glass va_end(va); 181*45313e83SSimon Glass *info.outstr = '\0'; 1825c411d88SSimon Glass 1835c411d88SSimon Glass return ret; 1845c411d88SSimon Glass } 185abeb272dSMarek Vasut 186abeb272dSMarek Vasut /* Note that size is ignored */ 187abeb272dSMarek Vasut int snprintf(char *buf, size_t size, const char *fmt, ...) 188abeb272dSMarek Vasut { 189*45313e83SSimon Glass struct printf_info info; 190abeb272dSMarek Vasut va_list va; 191abeb272dSMarek Vasut int ret; 192abeb272dSMarek Vasut 193abeb272dSMarek Vasut va_start(va, fmt); 194*45313e83SSimon Glass info.outstr = buf; 195*45313e83SSimon Glass info.putc = putc_outstr; 196*45313e83SSimon Glass ret = _vprintf(&info, fmt, va); 197abeb272dSMarek Vasut va_end(va); 198*45313e83SSimon Glass *info.outstr = '\0'; 199abeb272dSMarek Vasut 200abeb272dSMarek Vasut return ret; 201abeb272dSMarek Vasut } 202e2409139SSimon Glass 203e2409139SSimon Glass void __assert_fail(const char *assertion, const char *file, unsigned line, 204e2409139SSimon Glass const char *function) 205e2409139SSimon Glass { 206e2409139SSimon Glass /* This will not return */ 207e2409139SSimon Glass printf("%s:%u: %s: Assertion `%s' failed.", file, line, function, 208e2409139SSimon Glass assertion); 209e2409139SSimon Glass hang(); 210e2409139SSimon Glass } 211