aboutsummaryrefslogtreecommitdiff
path: root/ui/curses
diff options
context:
space:
mode:
authorPaul Oliver <contact@pauloliver.dev>2025-11-22 03:03:11 +0100
committerPaul Oliver <contact@pauloliver.dev>2025-11-24 16:49:04 +0100
commitc8fc429d9e5ed8ab0566729003d60ef41f578807 (patch)
treeda0c41a8e2b72ba2f32ee495440793bd73039ccb /ui/curses
parent0bc672fe6c263b9894af0cd211d006054215c7a9 (diff)
Improves logging system
Diffstat (limited to 'ui/curses')
-rw-r--r--ui/curses/ui.j2.c177
1 files changed, 174 insertions, 3 deletions
diff --git a/ui/curses/ui.j2.c b/ui/curses/ui.j2.c
index 4370774..9ebd387 100644
--- a/ui/curses/ui.j2.c
+++ b/ui/curses/ui.j2.c
@@ -11,6 +11,9 @@
{% set proc_field_width = 21 %}
{% set proc_page_lines = 12 %}
+{% set log_line_size = 1024 %}
+{% set log_line_count = 1024 %}
+
{% macro ctrl(x) %}('{{ x }}' & 0x1f){% endmacro %}
{% if not args.optimized %}
@@ -27,6 +30,7 @@ enum {
PAGE_PROCESS,
PAGE_WORLD,
PAGE_IPC,
+ PAGE_LOG,
PAGE_COUNT,
};
@@ -35,6 +39,7 @@ enum {
PAIR_NOUSE,
PAIR_NORMAL,
PAIR_HEADER,
+ PAIR_WARN,
PAIR_LIVE_PROC,
PAIR_SELECTED_PROC,
PAIR_FREE_CELL,
@@ -72,6 +77,12 @@ bool g_wcursor_mode;
int g_wcursor_x;
int g_wcursor_y;
uint64_t g_wcursor_pointed;
+uint64_t g_log_cnt;
+unsigned g_log_ptr;
+unsigned g_log_scroll;
+bool g_log_warns[{{ log_line_count }}];
+time_t g_log_times[{{ log_line_count }}];
+char g_logs[{{ log_line_count }}][{{ log_line_size }}];
uint64_t g_vlin;
uint64_t g_vsiz;
uint64_t g_vlin_rng;
@@ -310,7 +321,7 @@ void gfx_render(const struct Core *core, uint64_t pos, uint64_t zoom, uint64_t p
}
// ----------------------------------------------------------------------------
-// TUI functions
+// TUI generic functions
// ----------------------------------------------------------------------------
void ui_line_buff_free() {
if (g_line_buff) {
@@ -387,6 +398,9 @@ void ui_ulx_field(int l, const char *label, uint64_t value) {
ui_line(false, l, PAIR_NORMAL, A_NORMAL, "%-4s : %#18lx", label, value);
}
+// ----------------------------------------------------------------------------
+// Core page functions
+// ----------------------------------------------------------------------------
void ui_print_core(int l) {
ui_line(false, ++l, PAIR_HEADER, A_BOLD, "CORE [%d]", g_core);
ui_ulx_field(++l, "cycl", g_cores[g_core].cycl);
@@ -409,6 +423,9 @@ void ui_print_core(int l) {
{% endfor %}
}
+// ----------------------------------------------------------------------------
+// Process page functions
+// ----------------------------------------------------------------------------
int ui_proc_pair(uint64_t pix) {
if (pix == g_proc_selected) {
return PAIR_SELECTED_PROC;
@@ -566,6 +583,9 @@ void ui_print_process(int l) {
}
}
+// ----------------------------------------------------------------------------
+// World page functions
+// ----------------------------------------------------------------------------
void ui_world_resize() {
assert(g_wrld_zoom);
@@ -718,6 +738,9 @@ void ui_print_world(int l) {
}
}
+// ----------------------------------------------------------------------------
+// IPC page functions
+// ----------------------------------------------------------------------------
void ui_print_ipc_field(int l, uint64_t i, int color) {
uint8_t iinst = g_cores[g_core].iviv[i];
uint64_t iaddr = g_cores[g_core].ivav[i];
@@ -771,6 +794,118 @@ void ui_print_ipc(int l) {
ui_print_ipc_data();
}
+// ----------------------------------------------------------------------------
+// Log page functions
+// ----------------------------------------------------------------------------
+void ui_info_impl(const char *format, ...) {
+ g_log_warns[g_log_ptr] = false;
+ g_log_times[g_log_ptr] = time(NULL);
+
+ va_list args;
+ va_start(args, format);
+ vsnprintf(g_logs[g_log_ptr], {{ log_line_size }}, format, args);
+ va_end(args);
+
+ g_log_cnt++;
+ g_log_ptr = (g_log_ptr + 1) % {{ log_line_count }};
+}
+
+void ui_warn_impl(const char *format, ...) {
+ g_log_warns[g_log_ptr] = true;
+ g_log_times[g_log_ptr] = time(NULL);
+
+ va_list args;
+ va_start(args, format);
+ vsnprintf(g_logs[g_log_ptr], {{ log_line_size }}, format, args);
+ va_end(args);
+
+ g_log_cnt++;
+ g_log_ptr = (g_log_ptr + 1) % {{ log_line_count }};
+}
+
+void ui_clear_log_line(int line) {
+ assert(line >= 0 && line < LINES);
+ move(line, {{ pane_width }});
+ clrtoeol();
+}
+
+void ui_print_log_line(unsigned lptr, int line) {
+ assert(lptr < {{ log_line_count }});
+ assert(line >= 0 && line < LINES);
+ ui_clear_log_line(line);
+
+ // Prints a log entry
+ if (strlen(g_logs[lptr])) {
+ struct tm tm = *localtime(&g_log_times[lptr]);
+
+ // Timestamp
+ ui_field(
+ line,
+ {{ pane_width }},
+ PAIR_NORMAL,
+ A_NORMAL,
+ "%d-%02d-%02d %02d:%02d:%02d",
+ tm.tm_year + 1900,
+ tm.tm_mon + 1,
+ tm.tm_mday,
+ tm.tm_hour,
+ tm.tm_min,
+ tm.tm_sec
+ );
+
+ // Level
+ ui_field(
+ line,
+ {{ pane_width }} + 20,
+ g_log_warns[lptr] ? PAIR_WARN : PAIR_HEADER,
+ A_NORMAL,
+ g_log_warns[lptr] ? "WARN:" : "INFO:"
+ );
+
+ // Message
+ ui_field(
+ line,
+ {{ pane_width }} + 26,
+ PAIR_NORMAL,
+ A_NORMAL,
+ g_logs[lptr]
+ );
+ }
+}
+
+void ui_print_log(int l) {
+ l++;
+
+ ui_line(true, l++, PAIR_HEADER, A_BOLD, "LOG");
+ ui_ulx_field(l++, "lscr", g_log_scroll);
+ ui_ulx_field(l++, "lcnt", g_log_cnt);
+ ui_ulx_field(l++, "lptr", g_log_ptr);
+
+ unsigned lptr = g_log_ptr;
+ int line = LINES + g_log_scroll;
+
+ while (line) {
+ lptr = (lptr - 1 + {{ log_line_count }}) % {{ log_line_count }};
+ line--;
+
+ if (line < LINES) {
+ ui_print_log_line(lptr, line);
+ }
+
+ if (lptr == g_log_ptr) {
+ break;
+ }
+ }
+
+ while (line) {
+ line--;
+ ui_clear_log_line(line);
+ }
+}
+
+// ----------------------------------------------------------------------------
+// Main print function
+// ----------------------------------------------------------------------------
void ui_print() {
int l = 1;
@@ -799,11 +934,17 @@ void ui_print() {
case PAGE_IPC:
ui_print_ipc(l);
break;
+ case PAGE_LOG:
+ ui_print_log(l);
+ break;
default:
break;
}
}
+// ----------------------------------------------------------------------------
+// Control function
+// ----------------------------------------------------------------------------
void ev_vscroll(int ev) {
switch (g_page) {
case PAGE_PROCESS:
@@ -879,6 +1020,28 @@ void ev_vscroll(int ev) {
}
break;
+ case PAGE_LOG:
+ switch (ev) {
+ case 'W':
+ g_log_scroll += LINES;
+ g_log_scroll = g_log_scroll >= {{ log_line_count }} ? {{ log_line_count }} - 1 : g_log_scroll;
+ break;
+ case 'S':
+ g_log_scroll -= g_log_scroll < (uint64_t)LINES ? g_log_scroll : (uint64_t)LINES;
+ break;
+ case 'w':
+ g_log_scroll += 1;
+ g_log_scroll = g_log_scroll >= {{ log_line_count }} ? {{ log_line_count }} - 1 : g_log_scroll;
+ break;
+ case 's':
+ g_log_scroll -= g_log_scroll ? 1 : 0;
+ break;
+ case 'q':
+ g_log_scroll = 0;
+ break;
+ }
+
+ break;
default:
break;
}
@@ -1037,7 +1200,7 @@ void ev_handle() {
break;
case KEY_SLEFT:
clear();
- g_core = (g_core - 1) % {{ args.cores }};
+ g_core = (g_core + {{ args.cores }} - 1) % {{ args.cores }};
break;
case KEY_SRIGHT:
clear();
@@ -1045,7 +1208,7 @@ void ev_handle() {
break;
case KEY_LEFT:
clear();
- g_page = (g_page - 1) % PAGE_COUNT;
+ g_page = (g_page + PAGE_COUNT - 1) % PAGE_COUNT;
break;
case KEY_RIGHT:
clear();
@@ -1134,6 +1297,9 @@ void ev_handle() {
}
}
+// ----------------------------------------------------------------------------
+// Main functions
+// ----------------------------------------------------------------------------
void init() {
setlocale(LC_ALL, "");
@@ -1148,6 +1314,7 @@ void init() {
init_pair(PAIR_NORMAL, COLOR_WHITE, COLOR_BLACK );
init_pair(PAIR_HEADER, COLOR_BLUE, COLOR_BLACK );
+ init_pair(PAIR_WARN, COLOR_RED, COLOR_BLACK );
init_pair(PAIR_LIVE_PROC, COLOR_BLUE, COLOR_BLACK );
init_pair(PAIR_SELECTED_PROC, COLOR_YELLOW, COLOR_BLACK );
init_pair(PAIR_FREE_CELL, COLOR_BLACK, COLOR_BLUE );
@@ -1158,6 +1325,10 @@ void init() {
init_pair(PAIR_SELECTED_IP, COLOR_BLACK, COLOR_RED );
init_pair(PAIR_SELECTED_SP, COLOR_BLACK, COLOR_MAGENTA);
+ // Install loggers
+ g_info = ui_info_impl;
+ g_warn = ui_warn_impl;
+
{% if args.command == "new" %}
salis_init();
{% elif args.command == "load" %}