3 #include <sys/ttydefaults.h>
5 #include "../../util/sort.h"
6 #include "../../util/util.h"
7 #include "../../util/hist.h"
8 #include "../../util/debug.h"
9 #include "../../util/symbol.h"
10 #include "../browser.h"
11 #include "../helpline.h"
12 #include "../libslang.h"
14 /* 2048 lines should be enough for a script output */
15 #define MAX_LINES 2048
17 /* 160 bytes for one output line */
18 #define AVERAGE_LINE_LEN 160
21 struct list_head node
;
22 char line
[AVERAGE_LINE_LEN
];
25 struct perf_script_browser
{
27 struct list_head entries
;
28 const char *script_name
;
32 #define SCRIPT_NAMELEN 128
33 #define SCRIPT_MAX_NO 64
35 * Usually the full path for a script is:
36 * /home/username/libexec/perf-core/scripts/python/xxx.py
37 * /home/username/libexec/perf-core/scripts/perl/xxx.pl
38 * So 256 should be long enough to contain the full path.
40 #define SCRIPT_FULLPATH_LEN 256
43 * When success, will copy the full path of the selected script
44 * into the buffer pointed by script_name, and return 0.
45 * Return -1 on failure.
47 static int list_scripts(char *script_name
)
49 char *buf
, *names
[SCRIPT_MAX_NO
], *paths
[SCRIPT_MAX_NO
];
50 int i
, num
, choice
, ret
= -1;
52 /* Preset the script name to SCRIPT_NAMELEN */
53 buf
= malloc(SCRIPT_MAX_NO
* (SCRIPT_NAMELEN
+ SCRIPT_FULLPATH_LEN
));
57 for (i
= 0; i
< SCRIPT_MAX_NO
; i
++) {
58 names
[i
] = buf
+ i
* (SCRIPT_NAMELEN
+ SCRIPT_FULLPATH_LEN
);
59 paths
[i
] = names
[i
] + SCRIPT_NAMELEN
;
62 num
= find_scripts(names
, paths
);
64 choice
= ui__popup_menu(num
, names
);
65 if (choice
< num
&& choice
>= 0) {
66 strcpy(script_name
, paths
[choice
]);
75 static void script_browser__write(struct ui_browser
*browser
,
78 struct script_line
*sline
= list_entry(entry
, struct script_line
, node
);
79 bool current_entry
= ui_browser__is_current_entry(browser
, row
);
81 ui_browser__set_color(browser
, current_entry
? HE_COLORSET_SELECTED
:
84 slsmg_write_nstring(sline
->line
, browser
->width
);
87 static int script_browser__run(struct perf_script_browser
*browser
)
91 if (ui_browser__show(&browser
->b
, browser
->script_name
,
92 "Press <- or ESC to exit") < 0)
96 key
= ui_browser__run(&browser
->b
, 0);
98 /* We can add some special key handling here if needed */
102 ui_browser__hide(&browser
->b
);
107 int script_browse(const char *script_opt
)
109 char cmd
[SCRIPT_FULLPATH_LEN
*2], script_name
[SCRIPT_FULLPATH_LEN
];
113 int ret
= -1, nr_entries
= 0;
116 struct script_line
*sline
;
118 struct perf_script_browser script
= {
120 .refresh
= ui_browser__list_head_refresh
,
121 .seek
= ui_browser__list_head_seek
,
122 .write
= script_browser__write
,
124 .script_name
= script_name
,
127 INIT_LIST_HEAD(&script
.entries
);
129 /* Save each line of the output in one struct script_line object. */
130 buf
= zalloc((sizeof(*sline
)) * MAX_LINES
);
135 memset(script_name
, 0, SCRIPT_FULLPATH_LEN
);
136 if (list_scripts(script_name
))
139 sprintf(cmd
, "perf script -s %s ", script_name
);
142 strcat(cmd
, script_opt
);
146 strcat(cmd
, input_name
);
149 strcat(cmd
, " 2>&1");
151 fp
= popen(cmd
, "r");
155 while ((retlen
= getline(&line
, &len
, fp
)) != -1) {
156 strncpy(sline
->line
, line
, AVERAGE_LINE_LEN
);
158 /* If one output line is very large, just cut it short */
159 if (retlen
>= AVERAGE_LINE_LEN
) {
160 sline
->line
[AVERAGE_LINE_LEN
- 1] = '\0';
161 sline
->line
[AVERAGE_LINE_LEN
- 2] = '\n';
163 list_add_tail(&sline
->node
, &script
.entries
);
165 if (script
.b
.width
< retlen
)
166 script
.b
.width
= retlen
;
168 if (nr_entries
++ >= MAX_LINES
- 1)
173 if (script
.b
.width
> AVERAGE_LINE_LEN
)
174 script
.b
.width
= AVERAGE_LINE_LEN
;
179 script
.nr_lines
= nr_entries
;
180 script
.b
.nr_entries
= nr_entries
;
181 script
.b
.entries
= &script
.entries
;
183 ret
= script_browser__run(&script
);