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 vprintf(const char *fmt, va_list va) 44 { 45 char ch; 46 char *p; 47 unsigned int num; 48 char buf[12]; 49 unsigned int div; 50 51 while ((ch = *(fmt++))) { 52 if (ch != '%') { 53 putc(ch); 54 } else { 55 char lz = 0; 56 char w = 0; 57 58 ch = *(fmt++); 59 if (ch == '0') { 60 ch = *(fmt++); 61 lz = 1; 62 } 63 64 if (ch >= '0' && ch <= '9') { 65 w = 0; 66 while (ch >= '0' && ch <= '9') { 67 w = (w * 10) + ch - '0'; 68 ch = *fmt++; 69 } 70 } 71 bf = buf; 72 p = bf; 73 zs = 0; 74 75 switch (ch) { 76 case 0: 77 goto abort; 78 case 'u': 79 case 'd': 80 num = va_arg(va, unsigned int); 81 if (ch == 'd' && (int)num < 0) { 82 num = -(int)num; 83 out('-'); 84 } 85 if (!num) { 86 out_dgt(0); 87 } else { 88 for (div = 1000000000; div; div /= 10) 89 div_out(&num, div); 90 } 91 break; 92 case 'x': 93 num = va_arg(va, unsigned int); 94 if (!num) { 95 out_dgt(0); 96 } else { 97 for (div = 0x10000000; div; div /= 0x10) 98 div_out(&num, div); 99 } 100 break; 101 case 'c': 102 out((char)(va_arg(va, int))); 103 break; 104 case 's': 105 p = va_arg(va, char*); 106 break; 107 case '%': 108 out('%'); 109 default: 110 break; 111 } 112 113 *bf = 0; 114 bf = p; 115 while (*bf++ && w > 0) 116 w--; 117 while (w-- > 0) 118 putc(lz ? '0' : ' '); 119 if (p) { 120 while ((ch = *p++)) 121 putc(ch); 122 } 123 } 124 } 125 126 abort: 127 return 0; 128 } 129 130 int printf(const char *fmt, ...) 131 { 132 va_list va; 133 int ret; 134 135 va_start(va, fmt); 136 ret = vprintf(fmt, va); 137 va_end(va); 138 139 return ret; 140 } 141