1 /* 2 * Copyright (c) 2013 Kevin Wolf <kwolf@redhat.com> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 * THE SOFTWARE. 21 */ 22 23 #include "libc.h" 24 25 static void print_char(char c) 26 { 27 outb(0xe9, c); 28 } 29 30 static void print_str(char *s) 31 { 32 while (*s) { 33 print_char(*s++); 34 } 35 } 36 37 static void print_num(uint64_t value, int base) 38 { 39 char digits[] = "0123456789abcdef"; 40 char buf[32] = { 0 }; 41 int i = sizeof(buf) - 2; 42 43 do { 44 buf[i--] = digits[value % base]; 45 value /= base; 46 } while (value); 47 48 print_str(&buf[i + 1]); 49 } 50 51 void printf(const char *fmt, ...) 52 { 53 va_list ap; 54 uint64_t val; 55 char *str; 56 int base; 57 int has_long; 58 int alt_form; 59 60 va_start(ap, fmt); 61 62 for (; *fmt; fmt++) { 63 if (*fmt != '%') { 64 print_char(*fmt); 65 continue; 66 } 67 fmt++; 68 69 if (*fmt == '#') { 70 fmt++; 71 alt_form = 1; 72 } else { 73 alt_form = 0; 74 } 75 76 if (*fmt == 'l') { 77 fmt++; 78 if (*fmt == 'l') { 79 fmt++; 80 has_long = 2; 81 } else { 82 has_long = 1; 83 } 84 } else { 85 has_long = 0; 86 } 87 88 switch (*fmt) { 89 case 'x': 90 case 'p': 91 base = 16; 92 goto convert_number; 93 case 'd': 94 case 'i': 95 case 'u': 96 base = 10; 97 goto convert_number; 98 case 'o': 99 base = 8; 100 goto convert_number; 101 102 convert_number: 103 switch (has_long) { 104 case 0: 105 val = va_arg(ap, unsigned int); 106 break; 107 case 1: 108 val = va_arg(ap, unsigned long); 109 break; 110 case 2: 111 val = va_arg(ap, unsigned long long); 112 break; 113 } 114 115 if (alt_form && base == 16) { 116 print_str("0x"); 117 } 118 119 print_num(val, base); 120 break; 121 122 case 's': 123 str = va_arg(ap, char*); 124 print_str(str); 125 break; 126 case '%': 127 print_char(*fmt); 128 break; 129 default: 130 print_char('%'); 131 print_char(*fmt); 132 break; 133 } 134 } 135 136 va_end(ap); 137 } 138 139 140