print.c (2711B)
1 /* print.c 2 * 3 * Copyright 2011 Brian Swetland <swetland@frotz.net> 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #include <fw/lib.h> 19 20 static const char hex[16] = "0123456789ABCDEF"; 21 22 char *printhex(char *tmp, unsigned c, unsigned n) 23 { 24 tmp[c] = 0; 25 while (c-- > 0) { 26 tmp[c] = hex[n & 0x0F]; 27 n >>= 4; 28 } 29 30 return tmp; 31 } 32 33 char *print_unsigned(char *tmp, int len, unsigned n, int w) 34 { 35 len--; 36 tmp[len] = '\0'; 37 38 if (w < 0 && n == 0) { 39 tmp[--len] = '0'; 40 } else { 41 while ((len >= 0) && (n || (w > 0))) { 42 tmp[--len] = hex[n % 10]; 43 n /= 10; 44 w--; 45 } 46 } 47 48 return &tmp[len]; 49 } 50 51 char *print_signed(char *tmp, int len, signed n, int w) 52 { 53 char *s; 54 55 if (n >= 0) 56 return print_unsigned(tmp, len, n, w); 57 58 s = print_unsigned(tmp + 1, len - 1, n * -1, w - 1); 59 s--; 60 *s = '-'; 61 return s; 62 } 63 64 char *print_ufixed(char *tmp, int len, unsigned n) 65 { 66 char * s; 67 char * point; 68 69 n >>= 2; 70 71 /* XXX: does not account for overflow */ 72 n *= 15625; 73 s = print_unsigned(tmp + 1, len - 1, (n + 50000) / 100000 % 10, 1); 74 point = s - 1; 75 s = print_unsigned(tmp, (s - tmp), n / 1000000, -1); 76 *point = '.'; 77 78 return s; 79 } 80 81 char *print_fixed(char *tmp, int len, signed n) 82 { 83 char * s; 84 85 if (n >= 0) 86 return print_ufixed(tmp, len, n); 87 88 s = print_ufixed(tmp + 1, len - 1, n * -1); 89 s--; 90 *s = '-'; 91 92 return s; 93 } 94 95 void vprintx(void (*_putc)(unsigned), const char *fmt, va_list ap) { 96 unsigned c; 97 const char *s; 98 char tmp[16]; 99 100 while ((c = *fmt++)) { 101 if (c != '%') { 102 _putc(c); 103 continue; 104 } 105 106 switch((c = *fmt++)) { 107 case 0: 108 return; 109 110 case 'x': 111 s = printhex(tmp, 8, va_arg(ap, unsigned)); 112 break; 113 114 case 'h': 115 s = printhex(tmp, 4, va_arg(ap, unsigned)); 116 break; 117 118 case 'b': 119 s = printhex(tmp, 2, va_arg(ap, unsigned)); 120 break; 121 122 case 'u': 123 s = print_unsigned(tmp, sizeof(tmp), va_arg(ap, unsigned), -1); 124 break; 125 126 case 'd': 127 s = print_signed(tmp, sizeof(tmp), va_arg(ap, signed), -1); 128 break; 129 130 case 'f': 131 s = print_fixed(tmp, sizeof(tmp), va_arg(ap, signed)); 132 break; 133 134 case 's': 135 s = va_arg(ap, const char *); 136 break; 137 138 case 'c': 139 c = va_arg(ap, unsigned); /* fall through */ 140 141 default: 142 _putc(c); continue; 143 } 144 145 while (*s) 146 _putc(*s++); 147 } 148 } 149