|
|
1.1 ! root 1: /* A reduced version of the printf function. ! 2: ! 3: Copyright (C) 2011 Richard Henderson ! 4: ! 5: This file is part of QEMU PALcode. ! 6: ! 7: This program is free software; you can redistribute it and/or modify ! 8: it under the terms of the GNU General Public License as published by ! 9: the Free Software Foundation; either version 2 of the License or ! 10: (at your option) any later version. ! 11: ! 12: This program is distributed in the hope that it will be useful, ! 13: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text ! 15: of the GNU General Public License for more details. ! 16: ! 17: You should have received a copy of the GNU General Public License ! 18: along with this program; see the file COPYING. If not see ! 19: <http://www.gnu.org/licenses/>. */ ! 20: ! 21: #include <stdarg.h> ! 22: #include <stdbool.h> ! 23: #include <string.h> ! 24: #include "console.h" ! 25: ! 26: static int print_buf_pad(char *buf, int buflen, char *p, int width, int pad) ! 27: { ! 28: int len = buf + buflen - p; ! 29: int r = 0; ! 30: ! 31: if (width > len) ! 32: { ! 33: *--p = pad; ! 34: len++; ! 35: ! 36: while (width > buflen) ! 37: { ! 38: crb_puts(0, p, 1); ! 39: width--; ! 40: r++; ! 41: } ! 42: while (width > len) ! 43: *--p = pad, len++; ! 44: } ! 45: ! 46: crb_puts(0, p, len); ! 47: return r + len; ! 48: } ! 49: ! 50: static int print_decimal(unsigned long val, int width, int pad) ! 51: { ! 52: char buf[32]; ! 53: char *p = buf + sizeof(buf); ! 54: ! 55: if (val == 0) ! 56: *--p = '0'; ! 57: else ! 58: { ! 59: do ! 60: { ! 61: unsigned long d, r; ! 62: ! 63: /* Compiling with -Os results in a call to the division routine. ! 64: Do what the compiler ought to have done. */ ! 65: d = __builtin_alpha_umulh(val, 0xcccccccccccccccd); ! 66: d >>= 3; ! 67: r = val - (d * 10); ! 68: ! 69: *--p = r + '0'; ! 70: val = d; ! 71: } ! 72: while (val); ! 73: } ! 74: ! 75: return print_buf_pad(buf, sizeof(buf), p, width, pad); ! 76: } ! 77: ! 78: static int print_hex(unsigned long val, int width, char pad) ! 79: { ! 80: char buf[32]; ! 81: char *p = buf + sizeof(buf); ! 82: ! 83: if (val == 0) ! 84: *--p = '0'; ! 85: else ! 86: { ! 87: do ! 88: { ! 89: int d = val % 16; ! 90: *--p = (d < 10 ? '0' : 'a' - 10) + d; ! 91: val /= 16; ! 92: } ! 93: while (val); ! 94: } ! 95: ! 96: return print_buf_pad(buf, sizeof(buf), p, width, pad); ! 97: } ! 98: ! 99: int printf(const char *fmt, ...) ! 100: { ! 101: va_list args; ! 102: unsigned long val; ! 103: int r = 0; ! 104: ! 105: va_start(args, fmt); ! 106: ! 107: for (; *fmt ; fmt++) ! 108: if (*fmt != '%') ! 109: { ! 110: crb_puts(0, fmt, 1); ! 111: r++; ! 112: } ! 113: else ! 114: { ! 115: const char *percent = fmt; ! 116: bool is_long = false; ! 117: char pad = ' '; ! 118: int width = 0; ! 119: ! 120: restart: ! 121: switch (*++fmt) ! 122: { ! 123: case '%': ! 124: crb_puts(0, "%", 1); ! 125: r++; ! 126: break; ! 127: ! 128: case 'l': ! 129: is_long = true; ! 130: goto restart; ! 131: ! 132: case 'd': ! 133: if (is_long) ! 134: { ! 135: long d = va_arg (args, long); ! 136: if (d < 0) ! 137: { ! 138: crb_puts(0, "-", 1); ! 139: d = -d; ! 140: } ! 141: val = d; ! 142: } ! 143: else ! 144: { ! 145: int d = va_arg (args, int); ! 146: if (d < 0) ! 147: { ! 148: crb_puts(0, "-", 1); ! 149: d = -d; ! 150: r++; ! 151: } ! 152: val = d; ! 153: } ! 154: goto do_unsigned; ! 155: ! 156: case 'u': ! 157: if (is_long) ! 158: val = va_arg (args, unsigned long); ! 159: else ! 160: val = va_arg (args, unsigned int); ! 161: ! 162: do_unsigned: ! 163: r += print_decimal (val, width, pad); ! 164: break; ! 165: ! 166: case 'x': ! 167: if (is_long) ! 168: val = va_arg (args, unsigned long); ! 169: else ! 170: val = va_arg (args, unsigned int); ! 171: r += print_hex (val, width, pad); ! 172: break; ! 173: ! 174: case 's': ! 175: { ! 176: const char *s = va_arg (args, const char *); ! 177: int len = strlen(s); ! 178: crb_puts(0, s, len); ! 179: r += len; ! 180: } ! 181: break; ! 182: ! 183: case '0': ! 184: pad = '0'; ! 185: case '1' ... '9': ! 186: width = *fmt - '0'; ! 187: while (fmt[1] >= '0' && fmt[1] <= '9') ! 188: width = width * 10 + *++fmt - '0'; ! 189: goto restart; ! 190: ! 191: default: ! 192: { ! 193: int len = fmt - percent; ! 194: crb_puts(0, percent, len); ! 195: r += len; ! 196: } ! 197: break; ! 198: } ! 199: } ! 200: ! 201: va_end(args); ! 202: return r; ! 203: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.