2019-09-18 23:22:09 +03:00
|
|
|
#include "sys/string.h"
|
2019-09-16 12:40:00 +03:00
|
|
|
#include "sys/debug.h"
|
2019-03-23 13:12:50 +02:00
|
|
|
#include "sys/attr.h"
|
2019-09-18 23:22:09 +03:00
|
|
|
#include <stdint.h>
|
2019-03-23 13:12:50 +02:00
|
|
|
|
|
|
|
#if defined(ARCH_AMD64)
|
2019-10-10 10:34:38 +03:00
|
|
|
#include "sys/amd64/hw/con.h"
|
2019-09-23 11:40:44 +03:00
|
|
|
#include "sys/amd64/hw/rs232.h"
|
2019-03-23 13:12:50 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
static const char *s_debug_xs_set0 = "0123456789abcdef";
|
|
|
|
static const char *s_debug_xs_set1 = "0123456789ABCDEF";
|
|
|
|
|
2019-09-30 10:39:38 +03:00
|
|
|
void fmtsiz(char *out, size_t sz) {
|
|
|
|
static const char sizs[] = "KMGTPE???";
|
|
|
|
size_t f = sz, r = 0;
|
|
|
|
int pwr = 0;
|
|
|
|
size_t l = 0;
|
|
|
|
|
|
|
|
while (f >= 1536) {
|
|
|
|
r = ((f % 1024) * 10) / 1024;
|
|
|
|
f /= 1024;
|
|
|
|
++pwr;
|
|
|
|
}
|
|
|
|
|
|
|
|
debug_ds(f, out, 0, 0);
|
|
|
|
l = strlen(out);
|
|
|
|
|
|
|
|
if (pwr) {
|
|
|
|
out[l++] = '.';
|
|
|
|
out[l++] = '0' + r;
|
|
|
|
|
|
|
|
out[l++] = sizs[pwr - 1];
|
|
|
|
|
|
|
|
out[l++] = 'i';
|
|
|
|
}
|
|
|
|
|
|
|
|
out[l++] = 'B';
|
|
|
|
out[l++] = 0;
|
|
|
|
}
|
|
|
|
|
2019-03-23 13:12:50 +02:00
|
|
|
// TODO: make debugc a __weak function of a character
|
|
|
|
void debugc(int level, char c) {
|
|
|
|
#if defined(ARCH_AMD64)
|
|
|
|
rs232_send(RS232_COM0, c);
|
2019-10-10 10:34:38 +03:00
|
|
|
amd64_con_putc(c);
|
2019-03-23 13:12:50 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void debugs(int level, const char *s) {
|
|
|
|
char c;
|
|
|
|
while ((c = *(s++))) {
|
|
|
|
debugc(level, c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void debugspl(int level, const char *s, char p, size_t c) {
|
|
|
|
size_t l = strlen(s);
|
|
|
|
for (size_t i = l; i < c; ++i) {
|
|
|
|
debugc(level, p);
|
|
|
|
}
|
|
|
|
debugs(level, s);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void debugspr(int level, const char *s, char p, size_t c) {
|
|
|
|
size_t l = strlen(s);
|
|
|
|
debugs(level, s);
|
|
|
|
for (size_t i = l; i < c; ++i) {
|
|
|
|
debugc(level, p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void debugsp(int level, const char *s, char padc, int padl) {
|
|
|
|
if (padl > 0) {
|
|
|
|
debugspl(level, s, padc, padl);
|
|
|
|
} else {
|
|
|
|
debugspr(level, s, padc, -padl);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void debug_ds(int64_t x, char *res, int s, int sz) {
|
|
|
|
if (!x) {
|
|
|
|
res[0] = '0';
|
|
|
|
res[1] = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int c;
|
|
|
|
uint64_t v;
|
|
|
|
|
|
|
|
if (sz) {
|
|
|
|
if (s && x < 0) {
|
|
|
|
v = (uint64_t) -x;
|
|
|
|
} else {
|
|
|
|
s = 0;
|
|
|
|
v = (uint64_t) x;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (s && ((int32_t) x) < 0) {
|
|
|
|
v = (uint64_t) -((int32_t) x);
|
|
|
|
} else {
|
|
|
|
s = 0;
|
|
|
|
v = (uint64_t) x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
c = 0;
|
|
|
|
|
|
|
|
while (v) {
|
|
|
|
res[c++] = '0' + v % 10;
|
|
|
|
v /= 10;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s) {
|
|
|
|
res[c++] = '-';
|
|
|
|
}
|
|
|
|
|
|
|
|
res[c] = 0;
|
|
|
|
|
|
|
|
for (int i = 0, j = c - 1; i < j; ++i, --j) {
|
|
|
|
res[i] ^= res[j];
|
|
|
|
res[j] ^= res[i];
|
|
|
|
res[i] ^= res[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void debug_xs(uint64_t v, char *res, const char *set) {
|
|
|
|
if (!v) {
|
|
|
|
res[0] = '0';
|
|
|
|
res[1] = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int c = 0;
|
|
|
|
|
|
|
|
while (v) {
|
|
|
|
res[c++] = set[v & 0xF];
|
|
|
|
v >>= 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
res[c] = 0;
|
|
|
|
|
|
|
|
for (int i = 0, j = c - 1; i < j; ++i, --j) {
|
|
|
|
res[i] ^= res[j];
|
|
|
|
res[j] ^= res[i];
|
|
|
|
res[i] ^= res[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void debugf(int level, const char *f, ...) {
|
|
|
|
va_list args;
|
|
|
|
va_start(args, f);
|
|
|
|
debugfv(level, f, args);
|
|
|
|
va_end(args);
|
|
|
|
}
|
|
|
|
|
|
|
|
void debugfv(int level, const char *fmt, va_list args) {
|
|
|
|
char c;
|
|
|
|
union {
|
|
|
|
const char *v_string;
|
|
|
|
char v_char;
|
|
|
|
int32_t v_int32;
|
|
|
|
uint32_t v_uint32;
|
|
|
|
int64_t v_int64;
|
|
|
|
uint64_t v_uint64;
|
|
|
|
uintptr_t v_ptr;
|
|
|
|
} value;
|
|
|
|
char buf[64];
|
|
|
|
char padc;
|
|
|
|
int padn;
|
|
|
|
int padd;
|
|
|
|
|
|
|
|
while ((c = *fmt)) {
|
|
|
|
switch (c) {
|
|
|
|
case '%':
|
|
|
|
c = *(++fmt);
|
|
|
|
|
|
|
|
padc = ' ';
|
|
|
|
padd = 1;
|
|
|
|
padn = 0;
|
|
|
|
if (c == '0') {
|
|
|
|
padc = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c == '-') {
|
|
|
|
padd = -1;
|
|
|
|
c = *(++fmt);
|
|
|
|
}
|
|
|
|
|
|
|
|
while (c >= '0' && c <= '9') {
|
|
|
|
padn *= 10;
|
|
|
|
padn += padd * (int) (c - '0');
|
|
|
|
c = *(++fmt);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (c) {
|
|
|
|
case 'l':
|
|
|
|
c = *(++fmt);
|
|
|
|
switch (c) {
|
|
|
|
case 'd':
|
|
|
|
value.v_int64 = va_arg(args, int64_t);
|
|
|
|
debug_ds(value.v_int64, buf, 1, 1);
|
|
|
|
debugsp(level, buf, padc, padn);
|
|
|
|
break;
|
|
|
|
case 'u':
|
|
|
|
value.v_uint64 = va_arg(args, uint64_t);
|
|
|
|
debug_ds(value.v_uint64, buf, 0, 1);
|
|
|
|
debugsp(level, buf, padc, padn);
|
|
|
|
break;
|
|
|
|
case 'x':
|
|
|
|
value.v_uint64 = va_arg(args, uint64_t);
|
|
|
|
debug_xs(value.v_uint64, buf, s_debug_xs_set0);
|
|
|
|
debugsp(level, buf, padc, padn);
|
|
|
|
break;
|
|
|
|
case 'X':
|
|
|
|
value.v_uint64 = va_arg(args, uint64_t);
|
|
|
|
debug_xs(value.v_uint64, buf, s_debug_xs_set1);
|
|
|
|
debugsp(level, buf, padc, padn);
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
value.v_uint64 = va_arg(args, uint64_t);
|
|
|
|
debugc(level, '0');
|
|
|
|
debugc(level, 'x');
|
|
|
|
debug_xs(value.v_uint64, buf, s_debug_xs_set0);
|
|
|
|
debugspl(level, buf, '0', sizeof(uint64_t) * 2);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
debugc(level, '%');
|
|
|
|
debugc(level, 'l');
|
|
|
|
debugc(level, c);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
// char is promoted to int
|
|
|
|
value.v_char = va_arg(args, int);
|
|
|
|
debugc(level, value.v_char);
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
value.v_int64 = va_arg(args, int32_t);
|
|
|
|
debug_ds(value.v_int64 & 0xFFFFFFFF, buf, 1, 0);
|
|
|
|
debugsp(level, buf, padc, padn);
|
|
|
|
break;
|
|
|
|
case 'u':
|
|
|
|
value.v_uint64 = va_arg(args, uint32_t);
|
|
|
|
debug_ds(value.v_uint64 & 0xFFFFFFFF, buf, 0, 0);
|
|
|
|
debugsp(level, buf, padc, padn);
|
|
|
|
break;
|
|
|
|
case 'x':
|
|
|
|
value.v_uint64 = va_arg(args, uint32_t);
|
|
|
|
debug_xs(value.v_uint64 & 0xFFFFFFFF, buf, s_debug_xs_set0);
|
|
|
|
debugsp(level, buf, padc, padn);
|
|
|
|
break;
|
|
|
|
case 'X':
|
|
|
|
value.v_uint64 = va_arg(args, uint32_t);
|
|
|
|
debug_xs(value.v_uint64 & 0xFFFFFFFF, buf, s_debug_xs_set1);
|
|
|
|
debugsp(level, buf, padc, padn);
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
value.v_ptr = va_arg(args, uintptr_t);
|
|
|
|
debugc(level, '0');
|
|
|
|
debugc(level, 'x');
|
|
|
|
debug_xs(value.v_ptr, buf, s_debug_xs_set0);
|
|
|
|
debugspl(level, buf, '0', sizeof(uintptr_t) * 2);
|
|
|
|
break;
|
2019-09-30 10:39:38 +03:00
|
|
|
case 'S':
|
|
|
|
value.v_ptr = va_arg(args, uintptr_t);
|
|
|
|
fmtsiz(buf, value.v_ptr);
|
|
|
|
debugsp(level, buf, padc, padn);
|
|
|
|
break;
|
2019-03-23 13:12:50 +02:00
|
|
|
case 's':
|
|
|
|
value.v_string = va_arg(args, const char *);
|
|
|
|
debugsp(level, value.v_string ? value.v_string : "(null)", padc, padn);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
debugc(level, '%');
|
|
|
|
debugc(level, c);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
debugc(level, c);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
++fmt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|