#include <elf.h>#include <inttypes.h>#include <sys/ttydefaults.h>#include <string.h>#include "../../util/sort.h"#include "../../util/util.h"#include "../../util/hist.h"#include "../../util/debug.h"#include "../../util/symbol.h"#include "../browser.h"#include "../helpline.h"#include "../libslang.h" /* 2048 lines should be enough for a script output */#define MAX_LINES 2048 /* 160 bytes for one output line */#define AVERAGE_LINE_LEN 160 struct script_line { struct list_head node; char line[AVERAGE_LINE_LEN];}; struct perf_script_browser { struct ui_browser b; struct list_head entries; const char *script_name; int nr_lines;}; #define SCRIPT_NAMELEN 128#define SCRIPT_MAX_NO 64/* * Usually the full path for a script is: * /home/username/libexec/perf-core/scripts/python/xxx.py * /home/username/libexec/perf-core/scripts/perl/xxx.pl * So 256 should be long enough to contain the full path. */#define SCRIPT_FULLPATH_LEN 256 /* * When success, will copy the full path of the selected script * into the buffer pointed by script_name, and return 0. * Return -1 on failure. */static int list_scripts(char *script_name){ char *buf, *names[SCRIPT_MAX_NO], *paths[SCRIPT_MAX_NO]; int i, num, choice, ret = -1; /* Preset the script name to SCRIPT_NAMELEN */ buf = malloc(SCRIPT_MAX_NO * (SCRIPT_NAMELEN + SCRIPT_FULLPATH_LEN)); if (!buf) return ret; for (i = 0; i < SCRIPT_MAX_NO; i++) { names[i] = buf + i * (SCRIPT_NAMELEN + SCRIPT_FULLPATH_LEN); paths[i] = names[i] + SCRIPT_NAMELEN; } num = find_scripts(names, paths); if (num > 0) { choice = ui__popup_menu(num, names); if (choice < num && choice >= 0) { strcpy(script_name, paths[choice]); ret = 0; } } free(buf); return ret;} static void script_browser__write(struct ui_browser *browser, void *entry, int row){ struct script_line *sline = list_entry(entry, struct script_line, node); bool current_entry = ui_browser__is_current_entry(browser, row); ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED : HE_COLORSET_NORMAL); slsmg_write_nstring(sline->line, browser->width);} static int script_browser__run(struct perf_script_browser *browser){ int key; if (ui_browser__show(&browser->b, browser->script_name, "Press <- or ESC to exit") < 0) return -1; while (1) { key = ui_browser__run(&browser->b, 0); /* We can add some special key handling here if needed */ break; } ui_browser__hide(&browser->b); return key;} int script_browse(const char *script_opt){ char cmd[SCRIPT_FULLPATH_LEN*2], script_name[SCRIPT_FULLPATH_LEN]; char *line = NULL; size_t len = 0; ssize_t retlen; int ret = -1, nr_entries = 0; FILE *fp; void *buf; struct script_line *sline; struct perf_script_browser script = { .b = { .refresh = ui_browser__list_head_refresh, .seek = ui_browser__list_head_seek, .write = script_browser__write, }, .script_name = script_name, }; INIT_LIST_HEAD(&script.entries); /* Save each line of the output in one struct script_line object. */ buf = zalloc((sizeof(*sline)) * MAX_LINES); if (!buf) return -1; sline = buf; memset(script_name, 0, SCRIPT_FULLPATH_LEN); if (list_scripts(script_name)) goto exit; sprintf(cmd, "perf script -s %s ", script_name); if (script_opt) strcat(cmd, script_opt); if (input_name) { strcat(cmd, " -i "); strcat(cmd, input_name); } strcat(cmd, " 2>&1"); fp = popen(cmd, "r"); if (!fp) goto exit; while ((retlen = getline(&line, &len, fp)) != -1) { strncpy(sline->line, line, AVERAGE_LINE_LEN); /* If one output line is very large, just cut it short */ if (retlen >= AVERAGE_LINE_LEN) { sline->line[AVERAGE_LINE_LEN - 1] = '\0'; sline->line[AVERAGE_LINE_LEN - 2] = '\n'; } list_add_tail(&sline->node, &script.entries); if (script.b.width < retlen) script.b.width = retlen; if (nr_entries++ >= MAX_LINES - 1) break; sline++; } if (script.b.width > AVERAGE_LINE_LEN) script.b.width = AVERAGE_LINE_LEN; if (line) free(line); pclose(fp); script.nr_lines = nr_entries; script.b.nr_entries = nr_entries; script.b.entries = &script.entries; ret = script_browser__run(&script);exit: free(buf); return ret;}
#include <elf.h>
#include <inttypes.h>
#include <sys/ttydefaults.h>
#include <string.h>
#include "../../util/sort.h"
#include "../../util/util.h"
#include "../../util/hist.h"
#include "../../util/debug.h"
#include "../../util/symbol.h"
#include "../browser.h"
#include "../helpline.h"
#include "../libslang.h"
/* 2048 lines should be enough for a script output */
#define MAX_LINES 2048
/* 160 bytes for one output line */
#define AVERAGE_LINE_LEN 160
struct script_line {
struct list_head node;
char line[AVERAGE_LINE_LEN];
};
struct perf_script_browser {
struct ui_browser b;
struct list_head entries;
const char *script_name;
int nr_lines;
};
#define SCRIPT_NAMELEN 128
#define SCRIPT_MAX_NO 64
/*
* Usually the full path for a script is:
* /home/username/libexec/perf-core/scripts/python/xxx.py
* /home/username/libexec/perf-core/scripts/perl/xxx.pl
* So 256 should be long enough to contain the full path.
*/
#define SCRIPT_FULLPATH_LEN 256
/*
* When success, will copy the full path of the selected script
* into the buffer pointed by script_name, and return 0.
* Return -1 on failure.
*/
static int list_scripts(char *script_name)
{
char *buf, *names[SCRIPT_MAX_NO], *paths[SCRIPT_MAX_NO];
int i, num, choice, ret = -1;
/* Preset the script name to SCRIPT_NAMELEN */
buf = malloc(SCRIPT_MAX_NO * (SCRIPT_NAMELEN + SCRIPT_FULLPATH_LEN));
if (!buf)
return ret;
for (i = 0; i < SCRIPT_MAX_NO; i++) {
names[i] = buf + i * (SCRIPT_NAMELEN + SCRIPT_FULLPATH_LEN);
paths[i] = names[i] + SCRIPT_NAMELEN;
}
num = find_scripts(names, paths);
if (num > 0) {
choice = ui__popup_menu(num, names);
if (choice < num && choice >= 0) {
strcpy(script_name, paths[choice]);
ret = 0;
}
}
free(buf);
return ret;
}
static void script_browser__write(struct ui_browser *browser,
void *entry, int row)
{
struct script_line *sline = list_entry(entry, struct script_line, node);
bool current_entry = ui_browser__is_current_entry(browser, row);
ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
HE_COLORSET_NORMAL);
slsmg_write_nstring(sline->line, browser->width);
}
static int script_browser__run(struct perf_script_browser *browser)
{
int key;
if (ui_browser__show(&browser->b, browser->script_name,
"Press <- or ESC to exit") < 0)
return -1;
while (1) {
key = ui_browser__run(&browser->b, 0);
/* We can add some special key handling here if needed */
break;
}
ui_browser__hide(&browser->b);
return key;
}
int script_browse(const char *script_opt)
{
char cmd[SCRIPT_FULLPATH_LEN*2], script_name[SCRIPT_FULLPATH_LEN];
char *line = NULL;
size_t len = 0;
ssize_t retlen;
int ret = -1, nr_entries = 0;
FILE *fp;
void *buf;
struct script_line *sline;
struct perf_script_browser script = {
.b = {
.refresh = ui_browser__list_head_refresh,
.seek = ui_browser__list_head_seek,
.write = script_browser__write,
},
.script_name = script_name,
};
INIT_LIST_HEAD(&script.entries);
/* Save each line of the output in one struct script_line object. */
buf = zalloc((sizeof(*sline)) * MAX_LINES);
if (!buf)
return -1;
sline = buf;
memset(script_name, 0, SCRIPT_FULLPATH_LEN);
if (list_scripts(script_name))
goto exit;
sprintf(cmd, "perf script -s %s ", script_name);
if (script_opt)
strcat(cmd, script_opt);
if (input_name) {
strcat(cmd, " -i ");
strcat(cmd, input_name);
}
strcat(cmd, " 2>&1");
fp = popen(cmd, "r");
if (!fp)
goto exit;
while ((retlen = getline(&line, &len, fp)) != -1) {
strncpy(sline->line, line, AVERAGE_LINE_LEN);
/* If one output line is very large, just cut it short */
if (retlen >= AVERAGE_LINE_LEN) {
sline->line[AVERAGE_LINE_LEN - 1] = '\0';
sline->line[AVERAGE_LINE_LEN - 2] = '\n';
}
list_add_tail(&sline->node, &script.entries);
if (script.b.width < retlen)
script.b.width = retlen;
if (nr_entries++ >= MAX_LINES - 1)
break;
sline++;
}
if (script.b.width > AVERAGE_LINE_LEN)
script.b.width = AVERAGE_LINE_LEN;
if (line)
free(line);
pclose(fp);
script.nr_lines = nr_entries;
script.b.nr_entries = nr_entries;
script.b.entries = &script.entries;
ret = script_browser__run(&script);
exit:
free(buf);
return ret;
}