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 197d9cde10SStefan Roese static void out(char c) 207d9cde10SStefan Roese { 217d9cde10SStefan Roese *bf++ = c; 227d9cde10SStefan Roese } 237d9cde10SStefan Roese 247d9cde10SStefan Roese static void out_dgt(char dgt) 257d9cde10SStefan Roese { 26a5ecdd08SStefan Roese out(dgt + (dgt < 10 ? '0' : 'a' - 10)); 277d9cde10SStefan Roese zs = 1; 287d9cde10SStefan Roese } 297d9cde10SStefan Roese 30a5ecdd08SStefan Roese static void div_out(unsigned int *num, unsigned int div) 317d9cde10SStefan Roese { 327d9cde10SStefan Roese unsigned char dgt = 0; 337d9cde10SStefan Roese 34a5ecdd08SStefan Roese while (*num >= div) { 35a5ecdd08SStefan Roese *num -= div; 367d9cde10SStefan Roese dgt++; 377d9cde10SStefan Roese } 387d9cde10SStefan Roese 397d9cde10SStefan Roese if (zs || dgt > 0) 407d9cde10SStefan Roese out_dgt(dgt); 417d9cde10SStefan Roese } 427d9cde10SStefan Roese 43962a43ccSSjoerd Simons int vprintf(const char *fmt, va_list va) 447d9cde10SStefan Roese { 457d9cde10SStefan Roese char ch; 467d9cde10SStefan Roese char *p; 47a5ecdd08SStefan Roese unsigned int num; 48a5ecdd08SStefan Roese char buf[12]; 49a5ecdd08SStefan Roese unsigned int div; 507d9cde10SStefan Roese 517d9cde10SStefan Roese while ((ch = *(fmt++))) { 527d9cde10SStefan Roese if (ch != '%') { 537d9cde10SStefan Roese putc(ch); 547d9cde10SStefan Roese } else { 557d9cde10SStefan Roese char lz = 0; 567d9cde10SStefan Roese char w = 0; 577d9cde10SStefan Roese 587d9cde10SStefan Roese ch = *(fmt++); 597d9cde10SStefan Roese if (ch == '0') { 607d9cde10SStefan Roese ch = *(fmt++); 617d9cde10SStefan Roese lz = 1; 627d9cde10SStefan Roese } 637d9cde10SStefan Roese 647d9cde10SStefan Roese if (ch >= '0' && ch <= '9') { 657d9cde10SStefan Roese w = 0; 667d9cde10SStefan Roese while (ch >= '0' && ch <= '9') { 67a5ecdd08SStefan Roese w = (w * 10) + ch - '0'; 687d9cde10SStefan Roese ch = *fmt++; 697d9cde10SStefan Roese } 707d9cde10SStefan Roese } 717d9cde10SStefan Roese bf = buf; 727d9cde10SStefan Roese p = bf; 737d9cde10SStefan Roese zs = 0; 747d9cde10SStefan Roese 757d9cde10SStefan Roese switch (ch) { 767d9cde10SStefan Roese case 0: 777d9cde10SStefan Roese goto abort; 787d9cde10SStefan Roese case 'u': 797d9cde10SStefan Roese case 'd': 807d9cde10SStefan Roese num = va_arg(va, unsigned int); 817d9cde10SStefan Roese if (ch == 'd' && (int)num < 0) { 827d9cde10SStefan Roese num = -(int)num; 837d9cde10SStefan Roese out('-'); 847d9cde10SStefan Roese } 85a5ecdd08SStefan Roese for (div = 1000000000; div; div /= 10) 86a5ecdd08SStefan Roese div_out(&num, div); 877d9cde10SStefan Roese break; 887d9cde10SStefan Roese case 'x': 897d9cde10SStefan Roese num = va_arg(va, unsigned int); 90a5ecdd08SStefan Roese for (div = 0x10000000; div; div /= 0x10) 91a5ecdd08SStefan Roese div_out(&num, div); 927d9cde10SStefan Roese break; 937d9cde10SStefan Roese case 'c': 947d9cde10SStefan Roese out((char)(va_arg(va, int))); 957d9cde10SStefan Roese break; 967d9cde10SStefan Roese case 's': 977d9cde10SStefan Roese p = va_arg(va, char*); 987d9cde10SStefan Roese break; 997d9cde10SStefan Roese case '%': 1007d9cde10SStefan Roese out('%'); 1017d9cde10SStefan Roese default: 1027d9cde10SStefan Roese break; 1037d9cde10SStefan Roese } 1047d9cde10SStefan Roese 1057d9cde10SStefan Roese *bf = 0; 1067d9cde10SStefan Roese bf = p; 1077d9cde10SStefan Roese while (*bf++ && w > 0) 1087d9cde10SStefan Roese w--; 1097d9cde10SStefan Roese while (w-- > 0) 1107d9cde10SStefan Roese putc(lz ? '0' : ' '); 111*8e31681cSSimon Glass if (p) { 1127d9cde10SStefan Roese while ((ch = *p++)) 1137d9cde10SStefan Roese putc(ch); 1147d9cde10SStefan Roese } 1157d9cde10SStefan Roese } 116*8e31681cSSimon Glass } 1177d9cde10SStefan Roese 1187d9cde10SStefan Roese abort: 1197d9cde10SStefan Roese return 0; 1207d9cde10SStefan Roese } 121962a43ccSSjoerd Simons 122962a43ccSSjoerd Simons int printf(const char *fmt, ...) 123962a43ccSSjoerd Simons { 124962a43ccSSjoerd Simons va_list va; 125962a43ccSSjoerd Simons int ret; 126962a43ccSSjoerd Simons 127962a43ccSSjoerd Simons va_start(va, fmt); 128962a43ccSSjoerd Simons ret = vprintf(fmt, va); 129962a43ccSSjoerd Simons va_end(va); 130962a43ccSSjoerd Simons 131962a43ccSSjoerd Simons return ret; 132962a43ccSSjoerd Simons } 133