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 167d9cde10SStefan Roese static char *bf; 177d9cde10SStefan Roese static char zs; 187d9cde10SStefan Roese 195c411d88SSimon Glass /* Current position in sprintf() output string */ 205c411d88SSimon Glass static char *outstr; 215c411d88SSimon Glass 227d9cde10SStefan Roese static void out(char c) 237d9cde10SStefan Roese { 247d9cde10SStefan Roese *bf++ = c; 257d9cde10SStefan Roese } 267d9cde10SStefan Roese 277d9cde10SStefan Roese static void out_dgt(char dgt) 287d9cde10SStefan Roese { 29a5ecdd08SStefan Roese out(dgt + (dgt < 10 ? '0' : 'a' - 10)); 307d9cde10SStefan Roese zs = 1; 317d9cde10SStefan Roese } 327d9cde10SStefan Roese 33a5ecdd08SStefan Roese static void div_out(unsigned int *num, unsigned int div) 347d9cde10SStefan Roese { 357d9cde10SStefan Roese unsigned char dgt = 0; 367d9cde10SStefan Roese 37a5ecdd08SStefan Roese while (*num >= div) { 38a5ecdd08SStefan Roese *num -= div; 397d9cde10SStefan Roese dgt++; 407d9cde10SStefan Roese } 417d9cde10SStefan Roese 427d9cde10SStefan Roese if (zs || dgt > 0) 437d9cde10SStefan Roese out_dgt(dgt); 447d9cde10SStefan Roese } 457d9cde10SStefan Roese 465c411d88SSimon Glass int _vprintf(const char *fmt, va_list va, void (*putc)(const char ch)) 477d9cde10SStefan Roese { 487d9cde10SStefan Roese char ch; 497d9cde10SStefan Roese char *p; 50a5ecdd08SStefan Roese unsigned int num; 51a5ecdd08SStefan Roese char buf[12]; 52a5ecdd08SStefan Roese unsigned int div; 537d9cde10SStefan Roese 547d9cde10SStefan Roese while ((ch = *(fmt++))) { 557d9cde10SStefan Roese if (ch != '%') { 567d9cde10SStefan Roese putc(ch); 577d9cde10SStefan Roese } else { 581fb67608SSimon Glass bool lz = false; 591fb67608SSimon Glass int width = 0; 607d9cde10SStefan Roese 617d9cde10SStefan Roese ch = *(fmt++); 627d9cde10SStefan Roese if (ch == '0') { 637d9cde10SStefan Roese ch = *(fmt++); 647d9cde10SStefan Roese lz = 1; 657d9cde10SStefan Roese } 667d9cde10SStefan Roese 677d9cde10SStefan Roese if (ch >= '0' && ch <= '9') { 681fb67608SSimon Glass width = 0; 697d9cde10SStefan Roese while (ch >= '0' && ch <= '9') { 701fb67608SSimon Glass width = (width * 10) + ch - '0'; 717d9cde10SStefan Roese ch = *fmt++; 727d9cde10SStefan Roese } 737d9cde10SStefan Roese } 747d9cde10SStefan Roese bf = buf; 757d9cde10SStefan Roese p = bf; 767d9cde10SStefan Roese zs = 0; 777d9cde10SStefan Roese 787d9cde10SStefan Roese switch (ch) { 791fb67608SSimon Glass case '\0': 807d9cde10SStefan Roese goto abort; 817d9cde10SStefan Roese case 'u': 827d9cde10SStefan Roese case 'd': 837d9cde10SStefan Roese num = va_arg(va, unsigned int); 847d9cde10SStefan Roese if (ch == 'd' && (int)num < 0) { 857d9cde10SStefan Roese num = -(int)num; 867d9cde10SStefan Roese out('-'); 877d9cde10SStefan Roese } 8874b1320aSSimon Glass if (!num) { 8974b1320aSSimon Glass out_dgt(0); 9074b1320aSSimon Glass } else { 91a5ecdd08SStefan Roese for (div = 1000000000; div; div /= 10) 92a5ecdd08SStefan Roese div_out(&num, div); 9374b1320aSSimon Glass } 947d9cde10SStefan Roese break; 957d9cde10SStefan Roese case 'x': 967d9cde10SStefan Roese num = va_arg(va, unsigned int); 9774b1320aSSimon Glass if (!num) { 9874b1320aSSimon Glass out_dgt(0); 9974b1320aSSimon Glass } else { 100a5ecdd08SStefan Roese for (div = 0x10000000; div; div /= 0x10) 101a5ecdd08SStefan Roese div_out(&num, div); 10274b1320aSSimon Glass } 1037d9cde10SStefan Roese break; 1047d9cde10SStefan Roese case 'c': 1057d9cde10SStefan Roese out((char)(va_arg(va, int))); 1067d9cde10SStefan Roese break; 1077d9cde10SStefan Roese case 's': 1087d9cde10SStefan Roese p = va_arg(va, char*); 1097d9cde10SStefan Roese break; 1107d9cde10SStefan Roese case '%': 1117d9cde10SStefan Roese out('%'); 1127d9cde10SStefan Roese default: 1137d9cde10SStefan Roese break; 1147d9cde10SStefan Roese } 1157d9cde10SStefan Roese 1167d9cde10SStefan Roese *bf = 0; 1177d9cde10SStefan Roese bf = p; 1181fb67608SSimon Glass while (*bf++ && width > 0) 1191fb67608SSimon Glass width--; 1201fb67608SSimon Glass while (width-- > 0) 1217d9cde10SStefan Roese putc(lz ? '0' : ' '); 1228e31681cSSimon Glass if (p) { 1237d9cde10SStefan Roese while ((ch = *p++)) 1247d9cde10SStefan Roese putc(ch); 1257d9cde10SStefan Roese } 1267d9cde10SStefan Roese } 1278e31681cSSimon Glass } 1287d9cde10SStefan Roese 1297d9cde10SStefan Roese abort: 1307d9cde10SStefan Roese return 0; 1317d9cde10SStefan Roese } 132962a43ccSSjoerd Simons 133*da70b4d1SHans de Goede int vprintf(const char *fmt, va_list va) 134*da70b4d1SHans de Goede { 135*da70b4d1SHans de Goede return _vprintf(fmt, va, putc); 136*da70b4d1SHans de Goede } 137*da70b4d1SHans de Goede 138962a43ccSSjoerd Simons int printf(const char *fmt, ...) 139962a43ccSSjoerd Simons { 140962a43ccSSjoerd Simons va_list va; 141962a43ccSSjoerd Simons int ret; 142962a43ccSSjoerd Simons 143962a43ccSSjoerd Simons va_start(va, fmt); 1445c411d88SSimon Glass ret = _vprintf(fmt, va, putc); 145962a43ccSSjoerd Simons va_end(va); 146962a43ccSSjoerd Simons 147962a43ccSSjoerd Simons return ret; 148962a43ccSSjoerd Simons } 1495c411d88SSimon Glass 1505c411d88SSimon Glass static void putc_outstr(char ch) 1515c411d88SSimon Glass { 1525c411d88SSimon Glass *outstr++ = ch; 1535c411d88SSimon Glass } 1545c411d88SSimon Glass 155abeb272dSMarek Vasut int sprintf(char *buf, const char *fmt, ...) 1565c411d88SSimon Glass { 1575c411d88SSimon Glass va_list va; 1585c411d88SSimon Glass int ret; 1595c411d88SSimon Glass 1605c411d88SSimon Glass va_start(va, fmt); 1615c411d88SSimon Glass outstr = buf; 1625c411d88SSimon Glass ret = _vprintf(fmt, va, putc_outstr); 1635c411d88SSimon Glass va_end(va); 1645c411d88SSimon Glass *outstr = '\0'; 1655c411d88SSimon Glass 1665c411d88SSimon Glass return ret; 1675c411d88SSimon Glass } 168abeb272dSMarek Vasut 169abeb272dSMarek Vasut /* Note that size is ignored */ 170abeb272dSMarek Vasut int snprintf(char *buf, size_t size, const char *fmt, ...) 171abeb272dSMarek Vasut { 172abeb272dSMarek Vasut va_list va; 173abeb272dSMarek Vasut int ret; 174abeb272dSMarek Vasut 175abeb272dSMarek Vasut va_start(va, fmt); 1763191d840SSimon Glass outstr = buf; 1773191d840SSimon Glass ret = _vprintf(fmt, va, putc_outstr); 178abeb272dSMarek Vasut va_end(va); 1793191d840SSimon Glass *outstr = '\0'; 180abeb272dSMarek Vasut 181abeb272dSMarek Vasut return ret; 182abeb272dSMarek Vasut } 183