#include <iostream>
#include <sstream>
#include <string>
#include <cstdio>
#include "PluginHook.h"
#include "gtkutils.h"
#include <config/ConfigParser.h>
#include <config/PathConfig.h>
#include <config/config_utils.h>
#include <config/SearchPath.h>
int find_symbols(const std::string &fnam, std::vector<std::string> &v)
{
static char line[256];
std::ostringstream ocmd;
FILE *pf;
v.clear();
ocmd << "nm -C --defined " << fnam << " | grep ' T ' | grep -v '(' | cut -d ' ' -f 3 | sort";
pf = popen(ocmd.str().c_str(),"r");
while ( fgets(line,256, pf) )
{
if ( strstr(line,"no symbol") )
{
// no symbol
break;
}
else if ( strstr(line,"_fini") || strstr(line,"_init"))
{
continue;
}
std::string ss = trim_str(line);
ss = ss.substr( ss.find_last_of(' ')+1);
v.push_back( ss );
}
return pclose(pf);
}
std::string figure_out_lang(const std::string &lib)
{
std::string::size_type pos = lib.rfind('.');
if ( pos != lib.npos )
{
std::string lib_suff("so dll dylib");
std::string suffix = downcase( lib.substr(pos+1) );
if ( lib_suff.find(suffix) != lib_suff.npos )
return "c++";
}
return "python";
}
PluginHook::PluginHook(const std::string &L, const std::string &H) :
_lib(L), _hook(H)
{
}
PluginHook::~PluginHook()
{
}
void PluginHook::auto_connect()
{
SET_CONNECT(on_help);
SET_CONNECT(on_browse_lib);
SET_CONNECT(on_find_symbols);
SET_CONNECT(on_hook_selected);
}
void PluginHook::user_init()
{
if (!_lib.empty())
{
set_text("entryLibrary", _lib);
on_find_symbols(0, this);
}
}
void PluginHook::on_hook_selected(GtkWidget *w, PluginHook *ph)
{
GtkWidget *active = gtk_menu_get_active(GTK_MENU(w));
ph->_hook = gtk_widget_get_name(active);
}
void PluginHook::on_find_symbols(GtkWidget *w, PluginHook *ph)
{
if (ph->_lib.empty())
return;
std::vector<std::string> symb;
std::vector<std::string>::const_iterator ip;
std::string the_lib = ph->get_text("entryLibrary");
if (the_lib.empty())
return;
GtkWidget *optmenu = ph->get_widget("comboHook");
gtk_option_menu_remove_menu(GTK_OPTION_MENU(optmenu));
the_lib = PathConfig::find_library(the_lib);
find_symbols(the_lib, symb);
if ( !symb.empty() )
{
GtkWidget *menu = gtk_menu_new();
for (ip=symb.begin(); ip!=symb.end();ip++)
{
GtkWidget *item = gtk_menu_item_new_with_label(ip->c_str());
gtk_widget_set_name(item, (const gchar *)ip->c_str());
gtk_widget_show(item);
gtk_menu_append(GTK_MENU(menu), item);
}
gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), menu);
g_signal_connect(G_OBJECT(menu),"selection_done",G_CALLBACK(on_hook_selected), ph);
gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu),0);
}
}
void PluginHook::on_browse_lib(GtkWidget *w, PluginHook *P)
{
const char *filters[] = {"linux|*.so", "Mac OSX|*.dylib", "Windows|*.dll", "Python|*.py", "All|*", 0};
std::string ofile = ::get_file_name("Find shared library", a_OpenFile, 0, filters);
if (!ofile.empty())
{
P->_lib = ofile;
P->_lang = figure_out_lang(P->_lib);
P->set_text("entryLibrary", ofile);
}
}
void PluginHook::on_help(GtkWidget *, PluginHook *P)
{
}
void PluginHook::process_text(const std::string &s, GtkWidget *w)
{
std::string val = get_text(s);
if (s=="entryLibrary")
_lib = get_text(s);
else
_hook = get_text(s);
}