1a113ec98SAlex Bennée /* 2a113ec98SAlex Bennée * Copyright (C) 2015 Virtual Open Systems SAS 3a113ec98SAlex Bennée * Author: Alexander Spyridakis <a.spyridakis@virtualopensystems.com> 4a113ec98SAlex Bennée * 5a113ec98SAlex Bennée * printf based on implementation by Kevin Wolf <kwolf@redhat.com> 6a113ec98SAlex Bennée * 7a113ec98SAlex Bennée * This program is free software; you can redistribute it and/or modify 8a113ec98SAlex Bennée * it under the terms of the GNU General Public License version 2 as 9a113ec98SAlex Bennée * published by the Free Software Foundation. 10a113ec98SAlex Bennée * 11a113ec98SAlex Bennée * SPDX-License-Identifier: GPL-2.0-only 12a113ec98SAlex Bennée */ 13a113ec98SAlex Bennée 14a113ec98SAlex Bennée #include "minilib.h" 15a113ec98SAlex Bennée 16a113ec98SAlex Bennée typedef __builtin_va_list va_list; 17a113ec98SAlex Bennée #define va_start(ap, X) __builtin_va_start(ap, X) 18a113ec98SAlex Bennée #define va_arg(ap, type) __builtin_va_arg(ap, type) 19a113ec98SAlex Bennée #define va_end(ap) __builtin_va_end(ap) 20a113ec98SAlex Bennée 21a113ec98SAlex Bennée static void print_str(char *s) 22a113ec98SAlex Bennée { 23a113ec98SAlex Bennée while (*s) { 24a113ec98SAlex Bennée __sys_outc(*s++); 25a113ec98SAlex Bennée } 26a113ec98SAlex Bennée } 27a113ec98SAlex Bennée 28a113ec98SAlex Bennée static void print_num(unsigned long long value, int base) 29a113ec98SAlex Bennée { 30*7e3798edSRichard Henderson static const char digits[] = "0123456789abcdef"; 31a113ec98SAlex Bennée char buf[32]; 32a113ec98SAlex Bennée int i = sizeof(buf) - 2, j; 33a113ec98SAlex Bennée 34a113ec98SAlex Bennée /* Set the buffer to 0. See problem of before. */ 35a113ec98SAlex Bennée for (j = 0; j < 32; j++) { 36a113ec98SAlex Bennée buf[j] = 0; 37a113ec98SAlex Bennée } 38a113ec98SAlex Bennée 39a113ec98SAlex Bennée do { 40a113ec98SAlex Bennée buf[i--] = digits[value % base]; 41a113ec98SAlex Bennée value /= base; 42a113ec98SAlex Bennée } while (value); 43a113ec98SAlex Bennée 44a113ec98SAlex Bennée print_str(&buf[i + 1]); 45a113ec98SAlex Bennée } 46a113ec98SAlex Bennée 47a113ec98SAlex Bennée void ml_printf(const char *fmt, ...) 48a113ec98SAlex Bennée { 49a113ec98SAlex Bennée va_list ap; 50a113ec98SAlex Bennée char *str; 51a113ec98SAlex Bennée int base; 52a113ec98SAlex Bennée int has_long; 53a113ec98SAlex Bennée int alt_form; 54a113ec98SAlex Bennée unsigned long long val; 55a113ec98SAlex Bennée 56a113ec98SAlex Bennée va_start(ap, fmt); 57a113ec98SAlex Bennée 58a113ec98SAlex Bennée for (; *fmt; fmt++) { 59a113ec98SAlex Bennée if (*fmt != '%') { 60a113ec98SAlex Bennée __sys_outc(*fmt); 61a113ec98SAlex Bennée continue; 62a113ec98SAlex Bennée } 63a113ec98SAlex Bennée fmt++; 64a113ec98SAlex Bennée 65a113ec98SAlex Bennée if (*fmt == '#') { 66a113ec98SAlex Bennée fmt++; 67a113ec98SAlex Bennée alt_form = 1; 68a113ec98SAlex Bennée } else { 69a113ec98SAlex Bennée alt_form = 0; 70a113ec98SAlex Bennée } 71a113ec98SAlex Bennée 72a113ec98SAlex Bennée if (*fmt == 'l') { 73a113ec98SAlex Bennée fmt++; 74a113ec98SAlex Bennée if (*fmt == 'l') { 75a113ec98SAlex Bennée fmt++; 76a113ec98SAlex Bennée has_long = 2; 77a113ec98SAlex Bennée } else { 78a113ec98SAlex Bennée has_long = 1; 79a113ec98SAlex Bennée } 80a113ec98SAlex Bennée } else { 81a113ec98SAlex Bennée has_long = 0; 82a113ec98SAlex Bennée } 83a113ec98SAlex Bennée 84a113ec98SAlex Bennée switch (*fmt) { 85a113ec98SAlex Bennée case 'x': 86a113ec98SAlex Bennée case 'p': 87a113ec98SAlex Bennée base = 16; 88a113ec98SAlex Bennée goto convert_number; 89a113ec98SAlex Bennée case 'd': 90a113ec98SAlex Bennée case 'i': 91a113ec98SAlex Bennée case 'u': 92a113ec98SAlex Bennée base = 10; 93a113ec98SAlex Bennée goto convert_number; 94a113ec98SAlex Bennée case 'o': 95a113ec98SAlex Bennée base = 8; 96a113ec98SAlex Bennée goto convert_number; 97a113ec98SAlex Bennée 98a113ec98SAlex Bennée convert_number: 99a113ec98SAlex Bennée switch (has_long) { 100a113ec98SAlex Bennée case 0: 101a113ec98SAlex Bennée val = va_arg(ap, unsigned int); 102a113ec98SAlex Bennée break; 103a113ec98SAlex Bennée case 1: 104a113ec98SAlex Bennée val = va_arg(ap, unsigned long); 105a113ec98SAlex Bennée break; 106a113ec98SAlex Bennée case 2: 107a113ec98SAlex Bennée val = va_arg(ap, unsigned long long); 108a113ec98SAlex Bennée break; 109a113ec98SAlex Bennée } 110a113ec98SAlex Bennée 111a113ec98SAlex Bennée if (alt_form && base == 16) { 112a113ec98SAlex Bennée print_str("0x"); 113a113ec98SAlex Bennée } 114a113ec98SAlex Bennée 115a113ec98SAlex Bennée print_num(val, base); 116a113ec98SAlex Bennée break; 117a113ec98SAlex Bennée 118a113ec98SAlex Bennée case 's': 119a113ec98SAlex Bennée str = va_arg(ap, char*); 120a113ec98SAlex Bennée print_str(str); 121a113ec98SAlex Bennée break; 122936647d3SAlex Bennée case 'c': 123936647d3SAlex Bennée __sys_outc(va_arg(ap, int)); 124936647d3SAlex Bennée break; 125a113ec98SAlex Bennée case '%': 126a113ec98SAlex Bennée __sys_outc(*fmt); 127a113ec98SAlex Bennée break; 128a113ec98SAlex Bennée default: 129a113ec98SAlex Bennée __sys_outc('%'); 130a113ec98SAlex Bennée __sys_outc(*fmt); 131a113ec98SAlex Bennée break; 132a113ec98SAlex Bennée } 133a113ec98SAlex Bennée } 134a113ec98SAlex Bennée 135a113ec98SAlex Bennée va_end(ap); 136a113ec98SAlex Bennée } 137