2010-03-11 20:12:44 -03:00
# define _GNU_SOURCE
# include <stdio.h>
# undef _GNU_SOURCE
# include <stdlib.h>
# include <newt.h>
2010-03-12 10:48:12 -03:00
# include <sys/ttydefaults.h>
2010-03-11 20:12:44 -03:00
# include "cache.h"
# include "hist.h"
# include "session.h"
# include "sort.h"
# include "symbol.h"
2010-03-26 21:16:22 -03:00
struct ui_progress {
newtComponent form , scale ;
} ;
struct ui_progress * ui_progress__new ( const char * title , u64 total )
{
struct ui_progress * self = malloc ( sizeof ( * self ) ) ;
if ( self ! = NULL ) {
int cols ;
newtGetScreenSize ( & cols , NULL ) ;
cols - = 4 ;
newtCenteredWindow ( cols , 1 , title ) ;
self - > form = newtForm ( NULL , NULL , 0 ) ;
if ( self - > form = = NULL )
goto out_free_self ;
self - > scale = newtScale ( 0 , 0 , cols , total ) ;
if ( self - > scale = = NULL )
goto out_free_form ;
newtFormAddComponents ( self - > form , self - > scale , NULL ) ;
newtRefresh ( ) ;
}
return self ;
out_free_form :
newtFormDestroy ( self - > form ) ;
out_free_self :
free ( self ) ;
return NULL ;
}
void ui_progress__update ( struct ui_progress * self , u64 curr )
{
newtScaleSet ( self - > scale , curr ) ;
newtRefresh ( ) ;
}
void ui_progress__delete ( struct ui_progress * self )
{
newtFormDestroy ( self - > form ) ;
newtPopWindow ( ) ;
free ( self ) ;
}
static char browser__last_msg [ 1024 ] ;
int browser__show_help ( const char * format , va_list ap )
{
int ret ;
static int backlog ;
ret = vsnprintf ( browser__last_msg + backlog ,
sizeof ( browser__last_msg ) - backlog , format , ap ) ;
backlog + = ret ;
if ( browser__last_msg [ backlog - 1 ] = = ' \n ' ) {
newtPopHelpLine ( ) ;
newtPushHelpLine ( browser__last_msg ) ;
newtRefresh ( ) ;
backlog = 0 ;
}
return ret ;
}
2010-03-12 10:48:12 -03:00
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 ;
}
2010-04-03 16:30:44 -03:00
static int popup_menu ( int argc , char * const argv [ ] )
2010-03-24 16:40:14 -03:00
{
struct newtExitStruct es ;
int i , rc = - 1 , max_len = 5 ;
newtComponent listbox , form = newt_form__new ( ) ;
if ( form = = NULL )
return - 1 ;
listbox = newtListbox ( 0 , 0 , argc , NEWT_FLAG_RETURNEXIT ) ;
if ( listbox = = NULL )
goto out_destroy_form ;
newtFormAddComponents ( form , listbox , NULL ) ;
for ( i = 0 ; i < argc ; + + i ) {
int len = strlen ( argv [ i ] ) ;
if ( len > max_len )
max_len = len ;
if ( newtListboxAddEntry ( listbox , argv [ i ] , ( void * ) ( long ) i ) )
goto out_destroy_form ;
}
newtCenteredWindow ( max_len , argc , NULL ) ;
newtFormRun ( form , & es ) ;
rc = newtListboxGetCurrent ( listbox ) - NULL ;
if ( es . reason = = NEWT_EXIT_HOTKEY )
rc = - 1 ;
newtPopWindow ( ) ;
out_destroy_form :
newtFormDestroy ( form ) ;
return rc ;
}
static bool dialog_yesno ( const char * msg )
{
/* newtWinChoice should really be accepting const char pointers... */
char yes [ ] = " Yes " , no [ ] = " No " ;
return newtWinChoice ( NULL , no , yes , ( char * ) msg ) = = 2 ;
}
2010-03-22 17:52:49 -03:00
/*
* When debugging newt problems it was useful to be able to " unroll "
* the calls to newtCheckBoxTreeAdd { Array , Item } , so that we can generate
* a source file with the sequence of calls to these methods , to then
* tweak the arrays to get the intended results , so I ' m keeping this code
* here , may be useful again in the future .
*/
# undef NEWT_DEBUG
static void newt_checkbox_tree__add ( newtComponent tree , const char * str ,
void * priv , int * indexes )
{
# ifdef NEWT_DEBUG
/* Print the newtCheckboxTreeAddArray to tinker with its index arrays */
int i = 0 , len = 40 - strlen ( str ) ;
fprintf ( stderr ,
" \t newtCheckboxTreeAddItem(tree, %*.*s \" %s \" , (void *)%p, 0, " ,
len , len , " " , str , priv ) ;
while ( indexes [ i ] ! = NEWT_ARG_LAST ) {
if ( indexes [ i ] ! = NEWT_ARG_APPEND )
fprintf ( stderr , " %d, " , indexes [ i ] ) ;
else
fprintf ( stderr , " %s, " , " NEWT_ARG_APPEND " ) ;
+ + i ;
}
fprintf ( stderr , " %s " , " NEWT_ARG_LAST); \n " ) ;
fflush ( stderr ) ;
# endif
newtCheckboxTreeAddArray ( tree , str , priv , 0 , indexes ) ;
}
static char * callchain_list__sym_name ( struct callchain_list * self ,
char * bf , size_t bfsize )
{
2010-03-24 16:40:18 -03:00
if ( self - > ms . sym )
return self - > ms . sym - > name ;
2010-03-22 17:52:49 -03:00
snprintf ( bf , bfsize , " %#Lx " , self - > ip ) ;
return bf ;
}
static void __callchain__append_graph_browser ( struct callchain_node * self ,
newtComponent tree , u64 total ,
int * indexes , int depth )
{
struct rb_node * node ;
u64 new_total , remaining ;
int idx = 0 ;
if ( callchain_param . mode = = CHAIN_GRAPH_REL )
new_total = self - > children_hit ;
else
new_total = total ;
remaining = new_total ;
node = rb_first ( & self - > rb_root ) ;
while ( node ) {
struct callchain_node * child = rb_entry ( node , struct callchain_node , rb_node ) ;
struct rb_node * next = rb_next ( node ) ;
u64 cumul = cumul_hits ( child ) ;
struct callchain_list * chain ;
int first = true , printed = 0 ;
int chain_idx = - 1 ;
remaining - = cumul ;
indexes [ depth ] = NEWT_ARG_APPEND ;
indexes [ depth + 1 ] = NEWT_ARG_LAST ;
list_for_each_entry ( chain , & child - > val , list ) {
char ipstr [ BITS_PER_LONG / 4 + 1 ] ,
* alloc_str = NULL ;
const char * str = callchain_list__sym_name ( chain , ipstr , sizeof ( ipstr ) ) ;
if ( first ) {
double percent = cumul * 100.0 / new_total ;
first = false ;
if ( asprintf ( & alloc_str , " %2.2f%% %s " , percent , str ) < 0 )
str = " Not enough memory! " ;
else
str = alloc_str ;
} else {
indexes [ depth ] = idx ;
indexes [ depth + 1 ] = NEWT_ARG_APPEND ;
indexes [ depth + 2 ] = NEWT_ARG_LAST ;
+ + chain_idx ;
}
2010-03-24 16:40:19 -03:00
newt_checkbox_tree__add ( tree , str , & chain - > ms , indexes ) ;
2010-03-22 17:52:49 -03:00
free ( alloc_str ) ;
+ + printed ;
}
indexes [ depth ] = idx ;
if ( chain_idx ! = - 1 )
indexes [ depth + 1 ] = chain_idx ;
if ( printed ! = 0 )
+ + idx ;
__callchain__append_graph_browser ( child , tree , new_total , indexes ,
depth + ( chain_idx ! = - 1 ? 2 : 1 ) ) ;
node = next ;
}
}
static void callchain__append_graph_browser ( struct callchain_node * self ,
newtComponent tree , u64 total ,
int * indexes , int parent_idx )
{
struct callchain_list * chain ;
int i = 0 ;
indexes [ 1 ] = NEWT_ARG_APPEND ;
indexes [ 2 ] = NEWT_ARG_LAST ;
list_for_each_entry ( chain , & self - > val , list ) {
char ipstr [ BITS_PER_LONG / 4 + 1 ] , * str ;
if ( chain - > ip > = PERF_CONTEXT_MAX )
continue ;
if ( ! i + + & & sort__first_dimension = = SORT_SYM )
continue ;
str = callchain_list__sym_name ( chain , ipstr , sizeof ( ipstr ) ) ;
2010-03-24 16:40:19 -03:00
newt_checkbox_tree__add ( tree , str , & chain - > ms , indexes ) ;
2010-03-22 17:52:49 -03:00
}
indexes [ 1 ] = parent_idx ;
indexes [ 2 ] = NEWT_ARG_APPEND ;
indexes [ 3 ] = NEWT_ARG_LAST ;
__callchain__append_graph_browser ( self , tree , total , indexes , 2 ) ;
}
static void hist_entry__append_callchain_browser ( struct hist_entry * self ,
newtComponent tree , u64 total , int parent_idx )
{
struct rb_node * rb_node ;
int indexes [ 1024 ] = { [ 0 ] = parent_idx , } ;
int idx = 0 ;
struct callchain_node * chain ;
rb_node = rb_first ( & self - > sorted_chain ) ;
while ( rb_node ) {
chain = rb_entry ( rb_node , struct callchain_node , rb_node ) ;
switch ( callchain_param . mode ) {
case CHAIN_FLAT :
break ;
case CHAIN_GRAPH_ABS : /* falldown */
case CHAIN_GRAPH_REL :
callchain__append_graph_browser ( chain , tree , total , indexes , idx + + ) ;
break ;
case CHAIN_NONE :
default :
break ;
}
rb_node = rb_next ( rb_node ) ;
}
}
2010-03-11 20:12:44 -03:00
static size_t hist_entry__append_browser ( struct hist_entry * self ,
2010-03-22 17:52:49 -03:00
newtComponent tree , u64 total )
2010-03-11 20:12:44 -03:00
{
2010-03-31 11:33:40 -03:00
char s [ 256 ] ;
size_t ret ;
2010-03-11 20:12:44 -03:00
if ( symbol_conf . exclude_other & & ! self - > parent )
return 0 ;
2010-03-31 11:33:40 -03:00
ret = hist_entry__snprintf ( self , s , sizeof ( s ) , NULL ,
false , 0 , false , total ) ;
2010-03-22 17:52:49 -03:00
if ( symbol_conf . use_callchain ) {
int indexes [ 2 ] ;
indexes [ 0 ] = NEWT_ARG_APPEND ;
indexes [ 1 ] = NEWT_ARG_LAST ;
2010-03-24 16:40:19 -03:00
newt_checkbox_tree__add ( tree , s , & self - > ms , indexes ) ;
2010-03-22 17:52:49 -03:00
} else
2010-03-24 16:40:19 -03:00
newtListboxAppendEntry ( tree , s , & self - > ms ) ;
2010-03-22 17:52:49 -03:00
2010-03-31 11:33:40 -03:00
return ret ;
2010-03-11 20:12:44 -03:00
}
2010-04-03 11:54:35 -03:00
static void map_symbol__annotate_browser ( const struct map_symbol * self ,
const char * input_name )
2010-03-11 20:12:44 -03:00
{
FILE * fp ;
2010-03-12 12:46:47 -03:00
int cols , rows ;
2010-03-22 17:52:49 -03:00
newtComponent form , tree ;
2010-03-11 20:12:44 -03:00
struct newtExitStruct es ;
char * str ;
size_t line_len , max_line_len = 0 ;
size_t max_usable_width ;
char * line = NULL ;
2010-03-24 16:40:19 -03:00
if ( self - > sym = = NULL )
2010-03-11 20:12:44 -03:00
return ;
2010-04-03 11:54:35 -03:00
if ( asprintf ( & str , " perf annotate -i \" %s \" -d \" %s \" %s 2>&1 | expand " ,
input_name , self - > map - > dso - > name , self - > sym - > name ) < 0 )
2010-03-11 20:12:44 -03:00
return ;
fp = popen ( str , " r " ) ;
if ( fp = = NULL )
goto out_free_str ;
newtPushHelpLine ( " Press ESC to exit " ) ;
2010-03-12 12:46:47 -03:00
newtGetScreenSize ( & cols , & rows ) ;
2010-03-22 17:52:49 -03:00
tree = newtListbox ( 0 , 0 , rows - 5 , NEWT_FLAG_SCROLL ) ;
2010-03-11 20:12:44 -03:00
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 ;
2010-03-22 17:52:49 -03:00
newtListboxAppendEntry ( tree , line , NULL ) ;
2010-03-11 20:12:44 -03:00
}
fclose ( fp ) ;
free ( line ) ;
2010-03-12 12:46:47 -03:00
max_usable_width = cols - 22 ;
2010-03-11 20:12:44 -03:00
if ( max_line_len > max_usable_width )
max_line_len = max_usable_width ;
2010-03-22 17:52:49 -03:00
newtListboxSetWidth ( tree , max_line_len ) ;
2010-03-11 20:12:44 -03:00
2010-03-24 16:40:19 -03:00
newtCenteredWindow ( max_line_len + 2 , rows - 5 , self - > sym - > name ) ;
2010-03-12 10:48:12 -03:00
form = newt_form__new ( ) ;
2010-03-22 17:52:49 -03:00
newtFormAddComponents ( form , tree , NULL ) ;
2010-03-11 20:12:44 -03:00
newtFormRun ( form , & es ) ;
newtFormDestroy ( form ) ;
newtPopWindow ( ) ;
newtPopHelpLine ( ) ;
out_free_str :
free ( str ) ;
}
2010-03-24 16:40:14 -03:00
static const void * newt__symbol_tree_get_current ( newtComponent self )
{
if ( symbol_conf . use_callchain )
return newtCheckboxTreeGetCurrent ( self ) ;
return newtListboxGetCurrent ( self ) ;
}
2010-04-03 11:25:56 -03:00
static void hist_browser__selection ( newtComponent self , void * data )
2010-03-24 16:40:14 -03:00
{
2010-03-24 16:40:19 -03:00
const struct map_symbol * * symbol_ptr = data ;
2010-03-24 16:40:14 -03:00
* symbol_ptr = newt__symbol_tree_get_current ( self ) ;
}
2010-04-03 11:25:56 -03:00
struct hist_browser {
newtComponent form , tree ;
const struct map_symbol * selection ;
} ;
static struct hist_browser * hist_browser__new ( void )
{
struct hist_browser * self = malloc ( sizeof ( * self ) ) ;
2010-04-03 16:30:44 -03:00
if ( self ! = NULL )
self - > form = NULL ;
2010-04-03 11:25:56 -03:00
return self ;
}
static void hist_browser__delete ( struct hist_browser * self )
{
newtFormDestroy ( self - > form ) ;
newtPopWindow ( ) ;
free ( self ) ;
}
static int hist_browser__populate ( struct hist_browser * self , struct rb_root * hists ,
u64 nr_hists , u64 session_total )
2010-03-11 20:12:44 -03:00
{
2010-04-03 11:25:56 -03:00
int max_len = 0 , idx , cols , rows ;
struct ui_progress * progress ;
2010-03-11 20:12:44 -03:00
struct rb_node * nd ;
2010-03-26 21:16:22 -03:00
u64 curr_hist = 0 ;
2010-04-03 16:30:44 -03:00
char seq [ ] = " . " ;
char str [ 256 ] ;
if ( self - > form ) {
newtFormDestroy ( self - > form ) ;
newtPopWindow ( ) ;
}
snprintf ( str , sizeof ( str ) , " Samples: %Ld " ,
session_total ) ;
newtDrawRootText ( 0 , 0 , str ) ;
newtGetScreenSize ( NULL , & rows ) ;
if ( symbol_conf . use_callchain )
self - > tree = newtCheckboxTreeMulti ( 0 , 0 , rows - 5 , seq ,
NEWT_FLAG_SCROLL ) ;
else
self - > tree = newtListbox ( 0 , 0 , rows - 5 ,
( NEWT_FLAG_SCROLL |
NEWT_FLAG_RETURNEXIT ) ) ;
newtComponentAddCallback ( self - > tree , hist_browser__selection ,
& self - > selection ) ;
2010-03-26 21:16:22 -03:00
progress = ui_progress__new ( " Adding entries to the browser... " , nr_hists ) ;
if ( progress = = NULL )
return - 1 ;
2010-03-11 20:12:44 -03:00
2010-03-22 17:52:49 -03:00
idx = 0 ;
2010-03-11 20:12:44 -03:00
for ( nd = rb_first ( hists ) ; nd ; nd = rb_next ( nd ) ) {
struct hist_entry * h = rb_entry ( nd , struct hist_entry , rb_node ) ;
2010-04-03 16:30:44 -03:00
int len ;
if ( h - > filtered )
continue ;
len = hist_entry__append_browser ( h , self - > tree , session_total ) ;
2010-03-11 20:12:44 -03:00
if ( len > max_len )
max_len = len ;
2010-03-24 16:40:19 -03:00
if ( symbol_conf . use_callchain )
2010-04-03 11:25:56 -03:00
hist_entry__append_callchain_browser ( h , self - > tree ,
session_total , idx + + ) ;
2010-03-26 21:16:22 -03:00
+ + curr_hist ;
if ( curr_hist % 5 )
ui_progress__update ( progress , curr_hist ) ;
2010-03-11 20:12:44 -03:00
}
2010-03-26 21:16:22 -03:00
ui_progress__delete ( progress ) ;
2010-04-03 11:25:56 -03:00
newtGetScreenSize ( & cols , & rows ) ;
2010-03-22 17:52:49 -03:00
if ( max_len > cols )
max_len = cols - 3 ;
if ( ! symbol_conf . use_callchain )
2010-04-03 11:25:56 -03:00
newtListboxSetWidth ( self - > tree , max_len ) ;
2010-03-22 17:52:49 -03:00
newtCenteredWindow ( max_len + ( symbol_conf . use_callchain ? 5 : 0 ) ,
rows - 5 , " Report " ) ;
2010-04-03 11:25:56 -03:00
self - > form = newt_form__new ( ) ;
2010-04-03 16:30:44 -03:00
if ( self - > form = = NULL )
return - 1 ;
2010-04-03 11:25:56 -03:00
newtFormAddHotKey ( self - > form , ' A ' ) ;
newtFormAddHotKey ( self - > form , ' a ' ) ;
newtFormAddHotKey ( self - > form , NEWT_KEY_RIGHT ) ;
newtFormAddComponents ( self - > form , self - > tree , NULL ) ;
self - > selection = newt__symbol_tree_get_current ( self - > tree ) ;
return 0 ;
}
2010-04-03 22:44:37 -03:00
enum hist_filter {
HIST_FILTER__DSO ,
HIST_FILTER__THREAD ,
} ;
2010-04-03 16:30:44 -03:00
static u64 hists__filter_by_dso ( struct rb_root * hists , struct dso * dso ,
u64 * session_total )
{
struct rb_node * nd ;
u64 nr_hists = 0 ;
* session_total = 0 ;
for ( nd = rb_first ( hists ) ; nd ; nd = rb_next ( nd ) ) {
struct hist_entry * h = rb_entry ( nd , struct hist_entry , rb_node ) ;
if ( dso ! = NULL & & ( h - > ms . map = = NULL | | h - > ms . map - > dso ! = dso ) ) {
2010-04-03 22:44:37 -03:00
h - > filtered | = ( 1 < < HIST_FILTER__DSO ) ;
2010-04-03 16:30:44 -03:00
continue ;
}
2010-04-03 22:44:37 -03:00
h - > filtered & = ~ ( 1 < < HIST_FILTER__DSO ) ;
2010-04-03 16:30:44 -03:00
+ + nr_hists ;
* session_total + = h - > count ;
}
return nr_hists ;
}
2010-04-03 22:44:37 -03:00
static u64 hists__filter_by_thread ( struct rb_root * hists , const struct thread * thread ,
u64 * session_total )
{
struct rb_node * nd ;
u64 nr_hists = 0 ;
* session_total = 0 ;
for ( nd = rb_first ( hists ) ; nd ; nd = rb_next ( nd ) ) {
struct hist_entry * h = rb_entry ( nd , struct hist_entry , rb_node ) ;
if ( thread ! = NULL & & h - > thread ! = thread ) {
h - > filtered | = ( 1 < < HIST_FILTER__THREAD ) ;
continue ;
}
h - > filtered & = ~ ( 1 < < HIST_FILTER__THREAD ) ;
+ + nr_hists ;
* session_total + = h - > count ;
}
return nr_hists ;
}
static struct thread * hist_browser__selected_thread ( struct hist_browser * self )
{
int * indexes ;
if ( ! symbol_conf . use_callchain )
goto out ;
indexes = newtCheckboxTreeFindItem ( self - > tree , ( void * ) self - > selection ) ;
if ( indexes ) {
bool is_hist_entry = indexes [ 1 ] = = NEWT_ARG_LAST ;
free ( indexes ) ;
if ( is_hist_entry )
goto out ;
}
return NULL ;
out :
return * ( struct thread * * ) ( self - > selection + 1 ) ;
}
2010-04-03 11:25:56 -03:00
int perf_session__browse_hists ( struct rb_root * hists , u64 nr_hists ,
2010-04-03 11:54:35 -03:00
u64 session_total , const char * helpline ,
const char * input_name )
2010-04-03 11:25:56 -03:00
{
struct newtExitStruct es ;
2010-04-03 22:44:37 -03:00
bool dso_filtered = false , thread_filtered = false ;
2010-04-03 11:25:56 -03:00
int err = - 1 ;
struct hist_browser * browser = hist_browser__new ( ) ;
if ( browser = = NULL )
return - 1 ;
newtPushHelpLine ( helpline ) ;
if ( hist_browser__populate ( browser , hists , nr_hists , session_total ) < 0 )
goto out ;
2010-03-11 20:12:44 -03:00
while ( 1 ) {
2010-04-03 22:44:37 -03:00
const struct thread * thread ;
2010-04-03 16:30:44 -03:00
char * options [ 16 ] ;
int nr_options = 0 , choice = 0 , i ,
2010-04-03 22:44:37 -03:00
annotate = - 2 , zoom_dso = - 2 , zoom_thread = - 2 ;
2010-03-11 20:12:44 -03:00
2010-04-03 11:25:56 -03:00
newtFormRun ( browser - > form , & es ) ;
2010-03-24 16:40:14 -03:00
if ( es . reason = = NEWT_EXIT_HOTKEY ) {
2010-03-24 16:40:19 -03:00
if ( toupper ( es . u . key ) = = ' A ' )
goto do_annotate ;
2010-03-24 16:40:14 -03:00
if ( es . u . key = = NEWT_KEY_ESCAPE | |
toupper ( es . u . key ) = = ' Q ' | |
es . u . key = = CTRL ( ' c ' ) ) {
if ( dialog_yesno ( " Do you really want to exit? " ) )
break ;
else
continue ;
}
}
2010-04-03 16:30:44 -03:00
if ( browser - > selection - > sym ! = NULL & &
asprintf ( & options [ nr_options ] , " Annotate %s " ,
browser - > selection - > sym - > name ) > 0 )
annotate = nr_options + + ;
if ( browser - > selection - > map ! = NULL & &
asprintf ( & options [ nr_options ] , " Zoom %s %s DSO " ,
dso_filtered ? " out of " : " into " ,
( browser - > selection - > map - > dso - > kernel ? " the Kernel " :
browser - > selection - > map - > dso - > short_name ) ) > 0 )
zoom_dso = nr_options + + ;
2010-04-03 22:44:37 -03:00
thread = hist_browser__selected_thread ( browser ) ;
if ( thread ! = NULL & &
asprintf ( & options [ nr_options ] , " Zoom %s %s(%d) thread " ,
( thread_filtered ? " out of " : " into " ) ,
( thread - > comm_set ? thread - > comm : " " ) , thread - > pid ) > 0 )
zoom_thread = nr_options + + ;
2010-04-03 16:30:44 -03:00
options [ nr_options + + ] = ( char * ) " Exit " ;
2010-03-24 16:40:14 -03:00
choice = popup_menu ( nr_options , options ) ;
2010-04-03 16:30:44 -03:00
for ( i = 0 ; i < nr_options - 1 ; + + i )
free ( options [ i ] ) ;
2010-03-24 16:40:14 -03:00
if ( choice = = nr_options - 1 )
2010-03-11 20:12:44 -03:00
break ;
2010-04-03 22:44:37 -03:00
if ( choice = = - 1 )
continue ;
2010-03-24 16:40:19 -03:00
do_annotate :
2010-04-03 16:30:44 -03:00
if ( choice = = annotate ) {
2010-04-03 11:25:56 -03:00
if ( browser - > selection - > map - > dso - > origin = = DSO__ORIG_KERNEL ) {
2010-03-24 16:40:19 -03:00
newtPopHelpLine ( ) ;
newtPushHelpLine ( " No vmlinux file found, can't "
" annotate with just a "
" kallsyms file " ) ;
continue ;
}
2010-04-03 11:54:35 -03:00
map_symbol__annotate_browser ( browser - > selection ,
input_name ) ;
2010-04-03 22:44:37 -03:00
} else if ( choice = = zoom_dso ) {
nr_hists = hists__filter_by_dso ( hists ,
( dso_filtered ? NULL :
browser - > selection - > map - > dso ) ,
& session_total ) ;
2010-04-03 16:30:44 -03:00
dso_filtered = ! dso_filtered ;
if ( hist_browser__populate ( browser , hists , nr_hists , session_total ) < 0 )
goto out ;
2010-04-03 22:44:37 -03:00
} else if ( choice = = zoom_thread ) {
nr_hists = hists__filter_by_thread ( hists ,
( thread_filtered ? NULL : thread ) ,
& session_total ) ;
thread_filtered = ! thread_filtered ;
if ( hist_browser__populate ( browser , hists , nr_hists , session_total ) < 0 )
goto out ;
2010-03-24 16:40:19 -03:00
}
2010-03-11 20:12:44 -03:00
}
2010-04-03 11:25:56 -03:00
err = 0 ;
out :
hist_browser__delete ( browser ) ;
return err ;
2010-03-11 20:12:44 -03:00
}
void setup_browser ( void )
{
if ( ! isatty ( 1 ) )
return ;
use_browser = true ;
newtInit ( ) ;
newtCls ( ) ;
newtPushHelpLine ( " " ) ;
}
2010-03-22 13:10:25 -03:00
void exit_browser ( bool wait_for_ok )
2010-03-11 20:12:44 -03:00
{
2010-03-22 13:10:25 -03:00
if ( use_browser ) {
if ( wait_for_ok ) {
char title [ ] = " Fatal Error " , ok [ ] = " Ok " ;
newtWinMessage ( title , ok , browser__last_msg ) ;
}
2010-03-11 20:12:44 -03:00
newtFinished ( ) ;
2010-03-22 13:10:25 -03:00
}
2010-03-11 20:12:44 -03:00
}