You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
4.3 KiB
187 lines
4.3 KiB
#include "globals.h" |
|
|
|
// Functions addresses |
|
G_funcsType G_funcs; |
|
|
|
// Loaded modules |
|
G_libsType G_libs; |
|
|
|
void ClearGlobals() |
|
{ |
|
for(auto& it:G_libs) dlclose(it); |
|
} |
|
|
|
|
|
int LoadModule(const std::string& name, const void* p, const std::string& modname) |
|
{ |
|
const std::string spath=*(reinterpret_cast<const std::string*>(p)); |
|
|
|
// Load module |
|
void* handle; |
|
void* initfunc; |
|
std::string initname; |
|
|
|
if(0!=modname.size()) initname=modname; |
|
else |
|
{ |
|
// Remove directory name, if present |
|
initname=name.substr((name.rfind('/')!=std::string::npos)?(name.rfind('/')+1):0,std::string::npos); |
|
// Remove ".so" on the end of string |
|
if(initname.rfind(".so")!=std::string::npos) initname.erase(initname.rfind(".so"),std::string::npos); |
|
} |
|
initname+="_module_init"; |
|
|
|
// Check if module is statically linked or already loaded: dlopen'ed the main program |
|
handle=dlopen(nullptr,RTLD_LAZY|RTLD_GLOBAL); |
|
if(nullptr==handle) |
|
{ |
|
COUT(ERROR)<<std::endl<<"Something wrong: can't dlopen the main program"<<std::endl; |
|
return 1; |
|
} |
|
initfunc=dlsym(handle,initname.c_str()); |
|
|
|
if(nullptr==initfunc) // We not find it |
|
{ |
|
if('/'==name[0]) // Absolute path |
|
{ |
|
handle=dlopen(name.c_str(),RTLD_LAZY|RTLD_GLOBAL); |
|
if(nullptr==handle) handle=dlopen((name+".so").c_str(),RTLD_LAZY|RTLD_GLOBAL); |
|
} |
|
else // Relative path |
|
{ |
|
std::string curpath; |
|
size_t bpos=0,epos; |
|
// Check in spath |
|
do |
|
{ |
|
epos=spath.find(':',bpos); |
|
curpath=spath.substr(bpos,(std::string::npos==epos)?epos:(epos-bpos)); |
|
handle=dlopen((curpath+name).c_str(),RTLD_LAZY|RTLD_GLOBAL); |
|
if(nullptr!=handle) break; |
|
handle=dlopen((curpath+name+".so").c_str(),RTLD_LAZY|RTLD_GLOBAL); |
|
if(nullptr!=handle) break; |
|
bpos=epos+1; |
|
} while(std::string::npos!=epos); |
|
} |
|
if(nullptr==handle) |
|
{ |
|
COUT(ERROR)<<std::endl<<"Can't dlopen module "<<name<<std::endl; |
|
return 1; |
|
} |
|
G_libs.push_back(handle); |
|
initfunc=dlsym(handle,initname.c_str()); |
|
} |
|
|
|
if(nullptr==initfunc) |
|
{ |
|
COUT(ERROR)<<std::endl<<"Can't find initialising function "<<initname<<" in module "<<name<<std::endl; |
|
return 1; |
|
} |
|
|
|
int ret=(*reinterpret_cast<ModuleInitFunc>(initfunc))(p); |
|
if(0!=ret) COUT(ERROR)<<std::endl<<"Initialising function "<<initname<<" of module "<<name<<" returns error "<<ret<<std::endl; |
|
return ret; |
|
} |
|
|
|
|
|
void RegisterFunction(const std::string& name, Func func) |
|
{ |
|
G_funcs.emplace(name,func); |
|
} |
|
|
|
|
|
bool Save(const ObjectList* input) |
|
{ |
|
ObjectList::IndexType sz=input->Size(), i; |
|
if(sz<2 || sz%2==1 ) |
|
{ |
|
COUT(ERROR)<<"Number of save arguments must not be "<<sz<<std::endl; |
|
return false; |
|
} |
|
|
|
// Check arguments types |
|
for(i=0;i<sz/2;i++) |
|
{ |
|
if(!OBType<ObjectString>(input->At(i*2+1))) |
|
{ |
|
COUT(ERROR)<<"Save format is save(object_1,file_1,...,object_n,file_n) where file_i is string"<<std::endl; |
|
return false; |
|
} |
|
} |
|
|
|
// Save |
|
const ObjectBase* arg1; |
|
for(i=0;i<sz/2;i++) |
|
{ |
|
arg1=input->At(i*2); |
|
OBType<ObjectString> arg2(input->At(i*2+1)); |
|
if(!arg1->Save(arg2->Value().c_str())) |
|
{ |
|
COUT(ERROR)<<"Can't save object "<<arg1->Dump()<<" to file "<<arg2->Value()<<std::endl; |
|
return false; |
|
} |
|
} |
|
|
|
return true; |
|
} |
|
|
|
|
|
bool Print(const ObjectList* input) |
|
{ |
|
ObjectList::IndexType sz=input->Size(), i; |
|
if(sz==0) return true; |
|
|
|
// Print |
|
for(i=0;i<sz;i++) |
|
{ |
|
if(!input->At(i)->Print()) |
|
{ |
|
COUT(ERROR)<<"Unprintable object "<<input->At(i)->Dump()<<std::endl; |
|
return false; |
|
} |
|
} |
|
|
|
return true; |
|
} |
|
|
|
WordList Split(const std::string& str, const std::string& delims, bool allowempty) |
|
{ |
|
WordList wl; |
|
size_t pos=0,bpos; |
|
|
|
if(0==str.size()) return wl; |
|
if(0==delims.size()) |
|
{ |
|
wl.push_back(str); |
|
return wl; |
|
} |
|
|
|
if(allowempty) |
|
{ |
|
// Find first delimiter symbol |
|
pos=str.find_first_of(delims); |
|
wl.push_back(str.substr(0,pos)); // pos can be npos |
|
while(std::string::npos!=pos) |
|
{ |
|
bpos=pos+1; |
|
pos=str.find_first_of(delims,bpos); // bpos can be greater then length |
|
wl.push_back(str.substr(bpos,(std::string::npos==pos)?pos:(pos-bpos))); |
|
} |
|
} |
|
else |
|
{ |
|
while(true) |
|
{ |
|
// Find first nondelimiter symbol |
|
bpos=str.find_first_not_of(delims,pos); |
|
if(std::string::npos==bpos) break; // no nondelimiters |
|
// Find first delimiter symbol |
|
pos=str.find_first_of(delims,bpos); |
|
wl.push_back(str.substr(bpos,(std::string::npos==pos)?pos:(pos-bpos))); |
|
if(std::string::npos!=pos) pos++; |
|
else break; |
|
} |
|
} |
|
|
|
return wl; |
|
}
|
|
|