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
print_str(char * s)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
print_num(unsigned long long value,int base)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
ml_printf(const char * fmt,...)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