1 /* 2 * Tiny printf version for SPL 3 * 4 * Copied from: 5 * http://www.sparetimelabs.com/printfrevisited/printfrevisited.php 6 * 7 * Copyright (C) 2004,2008 Kustaa Nyholm 8 * 9 * SPDX-License-Identifier: LGPL-2.1+ 10 */ 11 12 #include <common.h> 13 #include <stdarg.h> 14 #include <serial.h> 15 16 static char *bf; 17 static char zs; 18 19 static void out(char c) 20 { 21 *bf++ = c; 22 } 23 24 static void out_dgt(char dgt) 25 { 26 out(dgt + (dgt < 10 ? '0' : 'a' - 10)); 27 zs = 1; 28 } 29 30 static void div_out(unsigned int *num, unsigned int div) 31 { 32 unsigned char dgt = 0; 33 34 while (*num >= div) { 35 *num -= div; 36 dgt++; 37 } 38 39 if (zs || dgt > 0) 40 out_dgt(dgt); 41 } 42 43 int printf(const char *fmt, ...) 44 { 45 va_list va; 46 char ch; 47 char *p; 48 unsigned int num; 49 char buf[12]; 50 unsigned int div; 51 52 va_start(va, fmt); 53 54 while ((ch = *(fmt++))) { 55 if (ch != '%') { 56 putc(ch); 57 } else { 58 char lz = 0; 59 char w = 0; 60 61 ch = *(fmt++); 62 if (ch == '0') { 63 ch = *(fmt++); 64 lz = 1; 65 } 66 67 if (ch >= '0' && ch <= '9') { 68 w = 0; 69 while (ch >= '0' && ch <= '9') { 70 w = (w * 10) + ch - '0'; 71 ch = *fmt++; 72 } 73 } 74 bf = buf; 75 p = bf; 76 zs = 0; 77 78 switch (ch) { 79 case 0: 80 goto abort; 81 case 'u': 82 case 'd': 83 num = va_arg(va, unsigned int); 84 if (ch == 'd' && (int)num < 0) { 85 num = -(int)num; 86 out('-'); 87 } 88 for (div = 1000000000; div; div /= 10) 89 div_out(&num, div); 90 break; 91 case 'x': 92 num = va_arg(va, unsigned int); 93 for (div = 0x10000000; div; div /= 0x10) 94 div_out(&num, div); 95 break; 96 case 'c': 97 out((char)(va_arg(va, int))); 98 break; 99 case 's': 100 p = va_arg(va, char*); 101 break; 102 case '%': 103 out('%'); 104 default: 105 break; 106 } 107 108 *bf = 0; 109 bf = p; 110 while (*bf++ && w > 0) 111 w--; 112 while (w-- > 0) 113 putc(lz ? '0' : ' '); 114 while ((ch = *p++)) 115 putc(ch); 116 } 117 } 118 119 abort: 120 va_end(va); 121 return 0; 122 } 123