original_kernel/tools/perf/util/newt.c

210 lines
4.3 KiB
C

#define _GNU_SOURCE
#include <stdio.h>
#undef _GNU_SOURCE
#include <stdlib.h>
#include <newt.h>
#include <sys/ttydefaults.h>
#include "cache.h"
#include "hist.h"
#include "session.h"
#include "sort.h"
#include "symbol.h"
static void newt_form__set_exit_keys(newtComponent self)
{
newtFormAddHotKey(self, NEWT_KEY_ESCAPE);
newtFormAddHotKey(self, 'Q');
newtFormAddHotKey(self, 'q');
newtFormAddHotKey(self, CTRL('c'));
}
static newtComponent newt_form__new(void)
{
newtComponent self = newtForm(NULL, NULL, 0);
if (self)
newt_form__set_exit_keys(self);
return self;
}
static size_t hist_entry__append_browser(struct hist_entry *self,
newtComponent listbox, u64 total)
{
char bf[1024];
size_t len;
FILE *fp;
if (symbol_conf.exclude_other && !self->parent)
return 0;
fp = fmemopen(bf, sizeof(bf), "w");
if (fp == NULL)
return 0;
len = hist_entry__fprintf(self, NULL, false, 0, fp, total);
fclose(fp);
newtListboxAppendEntry(listbox, bf, self);
return len;
}
static void hist_entry__annotate_browser(struct hist_entry *self)
{
FILE *fp;
int cols, rows;
newtComponent form, listbox;
struct newtExitStruct es;
char *str;
size_t line_len, max_line_len = 0;
size_t max_usable_width;
char *line = NULL;
if (self->sym == NULL)
return;
if (asprintf(&str, "perf annotate %s | expand", self->sym->name) < 0)
return;
fp = popen(str, "r");
if (fp == NULL)
goto out_free_str;
newtPushHelpLine("Press ESC to exit");
newtGetScreenSize(&cols, &rows);
listbox = newtListbox(0, 0, rows - 5, NEWT_FLAG_SCROLL);
while (!feof(fp)) {
if (getline(&line, &line_len, fp) < 0 || !line_len)
break;
while (line_len != 0 && isspace(line[line_len - 1]))
line[--line_len] = '\0';
if (line_len > max_line_len)
max_line_len = line_len;
newtListboxAppendEntry(listbox, line, NULL);
}
fclose(fp);
free(line);
max_usable_width = cols - 22;
if (max_line_len > max_usable_width)
max_line_len = max_usable_width;
newtListboxSetWidth(listbox, max_line_len);
newtCenteredWindow(max_line_len + 2, rows - 5, self->sym->name);
form = newt_form__new();
newtFormAddComponents(form, listbox, NULL);
newtFormRun(form, &es);
newtFormDestroy(form);
newtPopWindow();
newtPopHelpLine();
out_free_str:
free(str);
}
void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
const char *helpline)
{
struct sort_entry *se;
struct rb_node *nd;
unsigned int width;
char *col_width = symbol_conf.col_width_list_str;
int rows;
size_t max_len = 0;
char str[1024];
newtComponent form, listbox;
struct newtExitStruct es;
snprintf(str, sizeof(str), "Samples: %Ld", session_total);
newtDrawRootText(0, 0, str);
newtPushHelpLine(helpline);
newtGetScreenSize(NULL, &rows);
form = newt_form__new();
listbox = newtListbox(1, 1, rows - 2, (NEWT_FLAG_SCROLL |
NEWT_FLAG_BORDER |
NEWT_FLAG_RETURNEXIT));
list_for_each_entry(se, &hist_entry__sort_list, list) {
if (se->elide)
continue;
width = strlen(se->header);
if (se->width) {
if (symbol_conf.col_width_list_str) {
if (col_width) {
*se->width = atoi(col_width);
col_width = strchr(col_width, ',');
if (col_width)
++col_width;
}
}
*se->width = max(*se->width, width);
}
}
for (nd = rb_first(hists); nd; nd = rb_next(nd)) {
struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
size_t len = hist_entry__append_browser(h, listbox, session_total);
if (len > max_len)
max_len = len;
}
newtListboxSetWidth(listbox, max_len);
newtFormAddComponents(form, listbox, NULL);
while (1) {
struct hist_entry *selection;
newtFormRun(form, &es);
if (es.reason == NEWT_EXIT_HOTKEY)
break;
selection = newtListboxGetCurrent(listbox);
hist_entry__annotate_browser(selection);
}
newtFormDestroy(form);
}
int browser__show_help(const char *format, va_list ap)
{
int ret;
static int backlog;
static char msg[1024];
ret = vsnprintf(msg + backlog, sizeof(msg) - backlog, format, ap);
backlog += ret;
if (msg[backlog - 1] == '\n') {
newtPopHelpLine();
newtPushHelpLine(msg);
newtRefresh();
backlog = 0;
}
return ret;
}
bool use_browser;
void setup_browser(void)
{
if (!isatty(1))
return;
use_browser = true;
newtInit();
newtCls();
newtPushHelpLine(" ");
}
void exit_browser(void)
{
if (use_browser)
newtFinished();
}