Warning, cross-references for /kernel/util/printf.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include "types.h"
0019 #include "kernel.h"
0020 #include "acpi.h"
0021 #include "util/screen.h"
0022 #include "lwip/ip.h"
0023 #include "lwip/netif.h"
0024 #include "lwip/udp.h"
0025 #include "util/debug.h"
0026
0027 static uint32 base10_u32_divisors[10] = {
0028 1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1
0029 };
0030
0031 #if 0
0032 static uint64 base10_u64_divisors[20] = {
0033 10000000000000000000ULL, 1000000000000000000ULL, 100000000000000000ULL,
0034 10000000000000000ULL, 1000000000000000ULL, 100000000000000ULL,
0035 10000000000000ULL, 1000000000000ULL, 100000000000ULL, 10000000000ULL,
0036 1000000000ULL, 100000000ULL, 10000000ULL, 1000000ULL, 100000ULL, 10000ULL,
0037 1000ULL, 100ULL, 10ULL, 1ULL
0038 };
0039 #endif
0040
0041 void
0042 closure_vprintf (void putc_clo (void *, char), void *data, const char *fmt,
0043 va_list args)
0044 {
0045 int precision, width, mode, upper, ells;
0046 char padding;
0047 #define putc(c) putc_clo(data,c)
0048 while (*fmt) {
0049
0050 switch (*fmt) {
0051 case '\0':
0052 return;
0053 case '%':
0054 fmt++;
0055 precision = 0;
0056 width = 0;
0057 upper = 1;
0058 padding = ' ';
0059 ells = 0;
0060 #define PRINTF_MODE_PRECISION 1
0061 mode = 0;
0062
0063 while (*fmt) {
0064 switch (*fmt) {
0065 case 'p':{
0066
0067 uint32 x = va_arg (args, uint32);
0068 int i, li;
0069
0070 for (i = 0; i < 8; i++) {
0071 if ((li = (x >> ((7 - i) << 2)) & 0x0F) > 9)
0072 putc ('A' + li - 0x0A);
0073 else
0074 putc ('0' + li);
0075 }
0076 goto directive_finished;
0077 }
0078 case 'x':
0079 upper = 0;
0080 case 'X':{
0081
0082 uint64 x;
0083 int i, li, print_padding = 0, print_digits = 0;
0084 int w = (ells == 2 ? 16 : 8);
0085
0086 if (ells == 2)
0087 x = va_arg (args, uint64);
0088 else
0089 x = va_arg (args, uint32);
0090
0091 for (i = 0; i < w; i++) {
0092 li = (x >> (((w - 1) - i) << 2)) & 0x0F;
0093
0094 #define HANDLE_OPTIONS(q,max_w,end_i) \
0095 if (q != 0 || i == end_i) \
0096 print_digits = 1; \
0097 if (q == 0 && !print_digits && i >= (max_w - width)) \
0098 print_padding = 1; \
0099 if (q == 0 && !print_digits && i >= (max_w - precision)) \
0100 print_digits = 1; \
0101 if (q == 0 && print_padding && !print_digits) \
0102 putc(padding);
0103
0104 HANDLE_OPTIONS (li, w, (w-1));
0105
0106 if (print_digits) {
0107 if (li > 9)
0108 putc ((upper ? 'A' : 'a') + li - 0x0A);
0109 else
0110 putc ('0' + li);
0111 }
0112 }
0113
0114 goto directive_finished;
0115 }
0116 case 'u':{
0117
0118 uint32 x = va_arg (args, uint32);
0119 int i, q, print_padding = 0, print_digits = 0;
0120 uint32 *divisors = base10_u32_divisors;
0121
0122 for (i = 0; i < 10; i++) {
0123 q = x / divisors[i];
0124 x %= divisors[i];
0125
0126 HANDLE_OPTIONS (q, 10, 9);
0127
0128 if (print_digits)
0129 putc ('0' + q);
0130 }
0131
0132 goto directive_finished;
0133 }
0134 case 'd':{
0135
0136 signed long x = va_arg (args, signed long);
0137 int i, q, print_padding = 0, print_digits = 0;
0138 uint32 *divisors = base10_u32_divisors;
0139
0140 if (x < 0) {
0141 putc ('-');
0142 x *= -1;
0143 }
0144 for (i = 0; i < 10; i++) {
0145 q = x / divisors[i];
0146 x %= divisors[i];
0147
0148 HANDLE_OPTIONS (q, 10, 9);
0149
0150 if (print_digits)
0151 putc ('0' + q);
0152 }
0153
0154 goto directive_finished;
0155 }
0156 case 's':{
0157
0158 char *s = va_arg (args, char *);
0159 if (s) {
0160 if (precision > 0)
0161 while (*s && precision-- > 0)
0162 putc (*s++);
0163 else
0164 while (*s)
0165 putc (*s++);
0166 } else {
0167 putc ('('); putc ('n'); putc ('u'); putc ('l'); putc ('l'); putc (')');
0168 }
0169 goto directive_finished;
0170 }
0171 case 'c':{
0172
0173 char c = (char) va_arg (args, int);
0174
0175 putc (c);
0176 goto directive_finished;
0177 }
0178 case '%':{
0179
0180 putc ('%');
0181 goto directive_finished;
0182 }
0183 case 'l':
0184
0185 ells++;
0186 break;
0187 case '.':
0188 mode = PRINTF_MODE_PRECISION;
0189 break;
0190 default:
0191 if ('0' <= *fmt && *fmt <= '9') {
0192 if (mode == PRINTF_MODE_PRECISION) {
0193
0194 precision *= 10;
0195 precision += *fmt - '0';
0196 } else if (mode == 0 && width == 0 && *fmt == '0') {
0197
0198 padding = '0';
0199 } else {
0200
0201 width *= 10;
0202 width += *fmt - '0';
0203 }
0204 }
0205 break;
0206 }
0207 fmt++;
0208 }
0209 directive_finished:
0210 break;
0211 default:
0212
0213 putc (*fmt);
0214 break;
0215 }
0216 fmt++;
0217 }
0218 #undef putc
0219 }
0220
0221 static void
0222 putc_fun (void *f, char c)
0223 {
0224 void (*g) (char) = f;
0225 g (c);
0226 }
0227
0228 void
0229 fun_vprintf (void putc (char), const char *fmt, va_list args)
0230 {
0231 closure_vprintf (putc_fun, (void *) putc, fmt, args);
0232 }
0233
0234 void
0235 fun_printf (void putc (char), const char *fmt, ...)
0236 {
0237 va_list args;
0238 va_start (args, fmt);
0239 fun_vprintf (putc, fmt, args);
0240 va_end (args);
0241 }
0242
0243 void
0244 com1_printf (const char *fmt, ...)
0245 {
0246 va_list args;
0247 va_start (args, fmt);
0248 fun_vprintf (com1_putc, fmt, args);
0249 va_end (args);
0250 }
0251
0252
0253
0254
0255 #define UDP_LOGGING_PORT 4444
0256 #define UDP_LOGGING_NET_IF "en0"
0257 #define UDP_LOGGING_BUF_SIZE 256
0258
0259 #ifdef UDP_LOGGING
0260 static struct netif *logging_if = NULL;
0261 static struct udp_pcb *logging_pcb = NULL;
0262 static char logging_buf[UDP_LOGGING_BUF_SIZE];
0263 static int logging_idx = 0;
0264 static void
0265 udp_logging_putc (char c)
0266 {
0267 if (logging_idx < UDP_LOGGING_BUF_SIZE)
0268 logging_buf[logging_idx++] = c;
0269 }
0270
0271 static int
0272 send (uint8 *buf, uint32 len)
0273 {
0274 struct pbuf *p;
0275 struct ip_addr server_ip;
0276
0277
0278 server_ip.addr = logging_if->gw.addr;
0279 if (server_ip.addr == 0) return -1;
0280
0281 p = pbuf_alloc (PBUF_TRANSPORT, len, PBUF_RAM);
0282
0283 if (!p) return -1;
0284
0285 if (pbuf_take (p, buf, len) != ERR_OK) {
0286 pbuf_free (p);
0287 return -1;
0288 }
0289
0290 if (udp_sendto (logging_pcb, p, &server_ip, UDP_LOGGING_PORT) != ERR_OK) {
0291 pbuf_free (p);
0292 return -1;
0293 }
0294
0295 pbuf_free (p);
0296
0297 return len;
0298 }
0299
0300 void
0301 logger_printf (const char *fmt, ...)
0302 {
0303
0304 if (!mp_enabled) {
0305 va_list args;
0306 va_start (args, fmt);
0307 fun_vprintf (com1_putc, fmt, args);
0308 va_end (args);
0309 } else {
0310 if (!logging_if)
0311 logging_if = netif_find (UDP_LOGGING_NET_IF);
0312 if (!logging_pcb) {
0313 logging_pcb = udp_new ();
0314 if (!logging_pcb)
0315 panic ("logging_pcb == NULL");
0316 if (udp_bind (logging_pcb, IP_ADDR_ANY, 0) != ERR_OK)
0317 panic ("udp_bind of logging pcb failed");
0318 char *msg = "INITIALIZED UDP LOGGING\n";
0319 send ((u8 *) msg, strlen (msg));
0320 }
0321 logging_idx = 0;
0322 memset (logging_buf, 0, UDP_LOGGING_BUF_SIZE);
0323 va_list args;
0324 va_start (args, fmt);
0325 fun_vprintf (udp_logging_putc, fmt, args);
0326 va_end (args);
0327 send ((u8 *) logging_buf, logging_idx);
0328 }
0329 }
0330
0331 #else
0332
0333 void
0334 logger_printf (const char *fmt, ...)
0335 {
0336 va_list args;
0337 va_start (args, fmt);
0338 fun_vprintf (logger_putc, fmt, args);
0339 va_end (args);
0340 }
0341 #endif
0342
0343 static void
0344 _putc (char c)
0345 {
0346 _putchar (c);
0347 }
0348
0349 void
0350 printf (const char *fmt, ...)
0351 {
0352 va_list args;
0353 va_start (args, fmt);
0354 spinlock_lock (&screen_lock);
0355 fun_vprintf (_putc, fmt, args);
0356 spinlock_unlock (&screen_lock);
0357 va_end (args);
0358 }
0359
0360
0361 void
0362 _printf (const char *fmt, ...)
0363 {
0364 va_list args;
0365 va_start (args, fmt);
0366
0367 fun_vprintf (_putc, fmt, args);
0368
0369 va_end (args);
0370 }
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381