blob: 3d3a936acb67897a0173d8cf8886a2470240868a [file] [log] [blame]
Arnaldo Carvalho de Melof9224c52010-03-11 20:12:44 -03001#define _GNU_SOURCE
2#include <stdio.h>
3#undef _GNU_SOURCE
4
5#include <stdlib.h>
6#include <newt.h>
7
8#include "cache.h"
9#include "hist.h"
10#include "session.h"
11#include "sort.h"
12#include "symbol.h"
13
14static size_t hist_entry__append_browser(struct hist_entry *self,
15 newtComponent listbox, u64 total)
16{
17 char bf[1024];
18 size_t len;
19 FILE *fp;
20
21 if (symbol_conf.exclude_other && !self->parent)
22 return 0;
23
24 fp = fmemopen(bf, sizeof(bf), "w");
25 if (fp == NULL)
26 return 0;
27
28 len = hist_entry__fprintf(self, NULL, false, 0, fp, total);
29
30 fclose(fp);
31 newtListboxAppendEntry(listbox, bf, self);
32 return len;
33}
34
35static void hist_entry__annotate_browser(struct hist_entry *self)
36{
37 FILE *fp;
38 struct winsize ws;
39 newtComponent form, listbox;
40 struct newtExitStruct es;
41 char *str;
42 size_t line_len, max_line_len = 0;
43 size_t max_usable_width;
44 char *line = NULL;
45
46 if (self->sym == NULL)
47 return;
48
49 if (asprintf(&str, "perf annotate %s | expand", self->sym->name) < 0)
50 return;
51
52 fp = popen(str, "r");
53 if (fp == NULL)
54 goto out_free_str;
55
56 newtPushHelpLine("Press ESC to exit");
57 get_term_dimensions(&ws);
58 listbox = newtListbox(0, 0, ws.ws_row - 5, NEWT_FLAG_SCROLL);
59
60 while (!feof(fp)) {
61 if (getline(&line, &line_len, fp) < 0 || !line_len)
62 break;
63 while (line_len != 0 && isspace(line[line_len - 1]))
64 line[--line_len] = '\0';
65
66 if (line_len > max_line_len)
67 max_line_len = line_len;
68 newtListboxAppendEntry(listbox, line, NULL);
69 }
70 fclose(fp);
71 free(line);
72
73 max_usable_width = ws.ws_col - 22;
74 if (max_line_len > max_usable_width)
75 max_line_len = max_usable_width;
76
77 newtListboxSetWidth(listbox, max_line_len);
78
79 newtCenteredWindow(max_line_len + 2, ws.ws_row - 5, self->sym->name);
80 form = newtForm(NULL, NULL, 0);
81 newtFormAddHotKey(form, NEWT_KEY_ESCAPE);
82 newtFormAddComponents(form, listbox, NULL);
83
84 newtFormRun(form, &es);
85 newtFormDestroy(form);
86 newtPopWindow();
87 newtPopHelpLine();
88out_free_str:
89 free(str);
90}
91
92void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
93 const char *helpline)
94{
95 struct sort_entry *se;
96 struct rb_node *nd;
97 unsigned int width;
98 char *col_width = symbol_conf.col_width_list_str;
99 struct winsize ws;
100 size_t max_len = 0;
101 char str[1024];
102 newtComponent form, listbox;
103 struct newtExitStruct es;
104
105 snprintf(str, sizeof(str), "Samples: %Ld", session_total);
106 newtDrawRootText(0, 0, str);
107 newtPushHelpLine(helpline);
108
109 get_term_dimensions(&ws);
110
111 form = newtForm(NULL, NULL, 0);
112 newtFormAddHotKey(form, NEWT_KEY_ESCAPE);
113
114 listbox = newtListbox(1, 1, ws.ws_row - 2, (NEWT_FLAG_SCROLL |
115 NEWT_FLAG_BORDER |
116 NEWT_FLAG_RETURNEXIT));
117
118 list_for_each_entry(se, &hist_entry__sort_list, list) {
119 if (se->elide)
120 continue;
121 width = strlen(se->header);
122 if (se->width) {
123 if (symbol_conf.col_width_list_str) {
124 if (col_width) {
125 *se->width = atoi(col_width);
126 col_width = strchr(col_width, ',');
127 if (col_width)
128 ++col_width;
129 }
130 }
131 *se->width = max(*se->width, width);
132 }
133 }
134
135 for (nd = rb_first(hists); nd; nd = rb_next(nd)) {
136 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
137 size_t len = hist_entry__append_browser(h, listbox, session_total);
138 if (len > max_len)
139 max_len = len;
140 }
141
142 newtListboxSetWidth(listbox, max_len);
143 newtFormAddComponents(form, listbox, NULL);
144
145 while (1) {
146 struct hist_entry *selection;
147
148 newtFormRun(form, &es);
149 if (es.reason == NEWT_EXIT_HOTKEY)
150 break;
151 selection = newtListboxGetCurrent(listbox);
152 hist_entry__annotate_browser(selection);
153 }
154
155 newtFormDestroy(form);
156}
157
158int browser__show_help(const char *format, va_list ap)
159{
160 int ret;
161 static int backlog;
162 static char msg[1024];
163
164 ret = vsnprintf(msg + backlog, sizeof(msg) - backlog, format, ap);
165 backlog += ret;
166
167 if (msg[backlog - 1] == '\n') {
168 newtPopHelpLine();
169 newtPushHelpLine(msg);
170 newtRefresh();
171 backlog = 0;
172 }
173
174 return ret;
175}
176
177bool use_browser;
178
179void setup_browser(void)
180{
181 if (!isatty(1))
182 return;
183
184 use_browser = true;
185 newtInit();
186 newtCls();
187 newtPushHelpLine(" ");
188}
189
190void exit_browser(void)
191{
192 if (use_browser)
193 newtFinished();
194}