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