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 for (div = 1000000000; div; div /= 10) 86 div_out(&num, div); 87 break; 88 case 'x': 89 num = va_arg(va, unsigned int); 90 for (div = 0x10000000; div; div /= 0x10) 91 div_out(&num, div); 92 break; 93 case 'c': 94 out((char)(va_arg(va, int))); 95 break; 96 case 's': 97 p = va_arg(va, char*); 98 break; 99 case '%': 100 out('%'); 101 default: 102 break; 103 } 104 105 *bf = 0; 106 bf = p; 107 while (*bf++ && w > 0) 108 w--; 109 while (w-- > 0) 110 putc(lz ? '0' : ' '); 111 while ((ch = *p++)) 112 putc(ch); 113 } 114 } 115 116 abort: 117 return 0; 118 } 119 120 int printf(const char *fmt, ...) 121 { 122 va_list va; 123 int ret; 124 125 va_start(va, fmt); 126 ret = vprintf(fmt, va); 127 va_end(va); 128 129 return ret; 130 } 131