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 void* memcpy(void *dest, const void *src, int n) 26 { 27 char *d = dest; 28 const char *s = src; 29 30 while (n--) { 31 *d++ = *s++; 32 } 33 34 return dest; 35 } 36 37 static void print_char(char c) 38 { 39 outb(0xe9, c); 40 } 41 42 static void print_str(char *s) 43 { 44 while (*s) { 45 print_char(*s++); 46 } 47 } 48 49 static void print_num(uint64_t value, int base) 50 { 51 char digits[] = "0123456789abcdef"; 52 char buf[32] = { 0 }; 53 int i = sizeof(buf) - 2; 54 55 do { 56 buf[i--] = digits[value % base]; 57 value /= base; 58 } while (value); 59 60 print_str(&buf[i + 1]); 61 } 62 63 void printf(const char *fmt, ...) 64 { 65 va_list ap; 66 uint64_t val; 67 char *str; 68 int base; 69 int has_long; 70 int alt_form; 71 72 va_start(ap, fmt); 73 74 for (; *fmt; fmt++) { 75 if (*fmt != '%') { 76 print_char(*fmt); 77 continue; 78 } 79 fmt++; 80 81 if (*fmt == '#') { 82 fmt++; 83 alt_form = 1; 84 } else { 85 alt_form = 0; 86 } 87 88 if (*fmt == 'l') { 89 fmt++; 90 if (*fmt == 'l') { 91 fmt++; 92 has_long = 2; 93 } else { 94 has_long = 1; 95 } 96 } else { 97 has_long = 0; 98 } 99 100 switch (*fmt) { 101 case 'x': 102 case 'p': 103 base = 16; 104 goto convert_number; 105 case 'd': 106 case 'i': 107 case 'u': 108 base = 10; 109 goto convert_number; 110 case 'o': 111 base = 8; 112 goto convert_number; 113 114 convert_number: 115 switch (has_long) { 116 case 0: 117 val = va_arg(ap, unsigned int); 118 break; 119 case 1: 120 val = va_arg(ap, unsigned long); 121 break; 122 case 2: 123 val = va_arg(ap, unsigned long long); 124 break; 125 } 126 127 if (alt_form && base == 16) { 128 print_str("0x"); 129 } 130 131 print_num(val, base); 132 break; 133 134 case 's': 135 str = va_arg(ap, char*); 136 print_str(str); 137 break; 138 case '%': 139 print_char(*fmt); 140 break; 141 default: 142 print_char('%'); 143 print_char(*fmt); 144 break; 145 } 146 } 147 148 va_end(ap); 149 } 150 151 152