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

#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;
}