 f5385650c0
			
		
	
	
	f5385650c0
	
	
	
		
			
			Its perfectly fine to call free(NULL), so no need to clutter the source code with all those superfluous testing. Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/n/tip-uux5wpvevlerd42gqer13e7n@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
		
			
				
	
	
		
			187 lines
		
	
	
	
		
			4.2 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			187 lines
		
	
	
	
		
			4.2 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| #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;
 | |
| 
 | |
| 	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;
 | |
| }
 |