1 /*
2 * Copyright (c) 2006-2023 Ali Mashtizadeh
3 * All rights reserved.
4 */
5
6 #include <stdbool.h>
7 #include <stdint.h>
8 #include <stdarg.h>
9 #include <string.h>
10
11 #include <sys/kassert.h>
12
13 #include "../dev/console.h"
14
15 // static unsigned long getuint(va_list *ap, int lflag)
16 #define getuint(ap, lflag) \
17 (lflag == 8) ? va_arg(ap, uint64_t) : \
18 (lflag == 4) ? va_arg(ap, uint32_t) : \
19 (lflag == 2) ? va_arg(ap, uint32_t) : \
20 (lflag == 1) ? va_arg(ap, uint32_t) : 0
21
22 // static long getint(va_list *ap, int lflag)
23 #define getint(ap, lflag) \
24 (lflag == 8) ? va_arg(ap, int64_t) : \
25 (lflag == 4) ? va_arg(ap, int32_t) : \
26 (lflag == 2) ? va_arg(ap, int32_t) : \
27 (lflag == 1) ? va_arg(ap, int32_t) : 0
28
29 static const char *numberstring_lower = "0123456789abcdef";
30 static const char *numberstring_upper = "0123456789ABCDEF";
31
printnum(void (* func)(int,void *),void * handle,uint64_t num,int base,int width,int padc)32 static void printnum(void (*func)(int, void*),void *handle,
33 uint64_t num,int base,int width,int padc)
34 {
35 char buf[64];
36 char *p = buf;
37 int spaces;
38 if (base < 0)
39 {
40 base = -base;
41 do {
42 *p = numberstring_upper[num % base];
43 p++;
44 } while (num /= base);
45 } else {
46 do {
47 *p = numberstring_lower[num % base];
48 p++;
49 } while (num /= base);
50 }
51
52 // Print spacers (pre-number)
53 spaces = width - (p - buf);
54 if (padc == ' ' || padc == '0') {
55 while (spaces > 0)
56 {
57 func(padc, handle);
58 spaces--;
59 }
60 }
61
62 // Print Number
63 while (p != buf) {
64 p--;
65 func((int)*p, handle);
66 }
67
68 // Print spacers (post-number)
69 if (padc == '-') {
70 while (spaces > 0)
71 {
72 func(' ', handle);
73 spaces--;
74 }
75 }
76 }
77
kvprintf(char const * fmt,void (* func)(int,void *),void * handle,va_list ap)78 int kvprintf(char const *fmt, void (*func)(int,void *), void *handle, va_list ap)
79 {
80 const char *p;
81 int ch;
82 uint64_t unum;
83 int64_t num;
84 int lflag, width, padc;
85
86 while (1) {
87 while ((ch = *(unsigned char *)fmt++) != '%') {
88 if (ch == '\0') return -1;
89 func(ch, handle);
90 }
91
92 width = -1;
93 lflag = 4;
94 padc = ' ';
95 again:
96 switch (ch = *(unsigned char *)fmt++) {
97 case '-':
98 padc = '-';
99 goto again;
100 case '0':
101 padc = '0';
102 goto again;
103 case '1':
104 case '2':
105 case '3':
106 case '4':
107 case '5':
108 case '6':
109 case '7':
110 case '8':
111 case '9':
112 width = 0;
113 while (1) {
114 width = 10 * width + ch - '0';
115 ch = *fmt;
116 if (ch < '0' || ch > '9')
117 {
118 break;
119 }
120 fmt++;
121 if (ch == '\0')
122 {
123 fmt--;
124 goto again;
125 }
126 }
127 goto again;
128 case 'c':
129 func(va_arg(ap, int) & 0xff, handle);
130 break;
131 case 's': {
132 int spaces;
133
134 p = va_arg(ap, char *);
135 ASSERT(p != 0);
136 spaces = width - strlen(p);
137
138 if (padc == ' ') {
139 while (spaces > 0)
140 {
141 func(' ', handle);
142 spaces--;
143 }
144 }
145
146 while (*p != '\0')
147 {
148 func(*p++, handle);
149 }
150
151 if (padc == '-') {
152 while (spaces > 0)
153 {
154 func(' ', handle);
155 spaces--;
156 }
157 }
158 break;
159 }
160 case 'd':
161 num = getint(ap, lflag);
162 if (num < 0) {
163 func('-', handle);
164 unum = -num;
165 } else {
166 unum = num;
167 }
168 printnum(func, handle, unum, 10, width, padc);
169 break;
170 case 'u':
171 unum = getuint(ap, lflag);
172 printnum(func, handle, unum, 10, width, padc);
173 break;
174 case 'o':
175 unum = getuint(ap, lflag);
176 printnum(func, handle, unum, 8, width, padc);
177 break;
178 case 'p':
179 unum = (unsigned long)va_arg(ap, void *);
180 printnum(func, handle, unum, 8, width, padc);
181 break;
182 case 'x':
183 unum = getuint(ap, lflag);
184 printnum(func, handle, unum, 16, width, padc);
185 break;
186 case 'X':
187 unum = getuint(ap, lflag);
188 printnum(func, handle, unum, -16, width, padc);
189 break;
190 case 'l':
191 lflag = 8;
192 goto again;
193 case '%':
194 default: // Print Literally
195 func(ch, handle);
196 break;
197 }
198 }
199 return 0;
200 }
201
consoleputc(int c,void * handle)202 void consoleputc(int c,void* handle)
203 {
204 if (c == '\n') {
205 Console_Putc('\r');
206 }
207 Console_Putc(c);
208 }
209
kprintf(const char * fmt,...)210 int kprintf(const char *fmt, ...)
211 {
212 int ret;
213 va_list ap;
214
215 va_start(ap, fmt);
216 ret = kvprintf(fmt, consoleputc, 0, ap);
217 va_end(ap);
218
219 return ret;
220 }
221
Debug_Assert(const char * fmt,...)222 void Debug_Assert(const char *fmt, ...)
223 {
224 va_list ap;
225
226 va_start(ap, fmt);
227 kvprintf(fmt, consoleputc, 0, ap);
228 va_end(ap);
229
230 #if 0
231 kprintf("PC %lx FP %lx\n", __builtin_return_address(0), __builtin_frame_address(0));
232 kprintf("PC %lx FP %lx\n", __builtin_return_address(1), __builtin_frame_address(1));
233 kprintf("PC %lx FP %lx\n", __builtin_return_address(2), __builtin_frame_address(2));
234 kprintf("PC %lx FP %lx\n", __builtin_return_address(3), __builtin_frame_address(3));
235 kprintf("PC %lx FP %lx\n", __builtin_return_address(4), __builtin_frame_address(4));
236 kprintf("PC %lx FP %lx\n", __builtin_return_address(5), __builtin_frame_address(5));
237 #endif
238
239 Panic("");
240 }
241
242