00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <string>
00011 #include <map>
00012 #include <stdlib.h>
00013
00014 #ifndef SEEXPR_WIN32
00015 #include <dlfcn.h>
00016 #include <dirent.h>
00017 #endif
00018
00019 #include "SeExpression.h"
00020 #include "SeExprFunc.h"
00021 #include "SeExprNode.h"
00022 #include "SeExprBuiltins.h"
00023
00024 #include "SeMutex.h"
00025
00026 namespace {
00027
00028 class FuncTable {
00029 public:
00030 FuncTable()
00031 :_inited(false)
00032 {}
00033
00034 ~FuncTable(){
00035 funcmap.clear();
00036 #ifdef SEEXPR_WIN32
00037 #else
00038 for(size_t i=0;i<dynamicLibraries.size();i++){
00039 dlclose(dynamicLibraries[i]);
00040 }
00041 #endif
00042 }
00043
00044 void define(const char* name, SeExprFunc f,const char* docString=0) {
00045 if(docString) funcmap[name] = FuncMapItem(std::string(docString),f);
00046 else funcmap[name] = FuncMapItem(name,f);
00047 }
00048
00049 const SeExprFunc* lookup(const std::string& name)
00050 {
00051 FuncMap::iterator iter;
00052 if ((iter = funcmap.find(name)) != funcmap.end())
00053 return &iter->second.second;
00054 return 0;
00055 }
00056 void initIfNeeded();
00057 void initBuiltins();
00058
00059 void getFunctionNames(std::vector<std::string>& names)
00060 {
00061 for(FuncMap::iterator i=funcmap.begin();i!=funcmap.end();++i)
00062 names.push_back(i->first);
00063 }
00064
00065 std::string getDocString(const char* functionName)
00066 {
00067 FuncMap::iterator i=funcmap.find(functionName);
00068 if(i==funcmap.end()) return "";
00069 else return i->second.first;
00070 }
00071
00072 void addLibraryReference(void* lib)
00073 {
00074 dynamicLibraries.push_back(lib);
00075 }
00076
00077 private:
00078 bool _inited;
00079 typedef std::pair<std::string,SeExprFunc> FuncMapItem;
00080 typedef std::map<std::string,FuncMapItem> FuncMap;
00081 std::vector<void*> dynamicLibraries;
00082 FuncMap funcmap;
00083 };
00084
00085 FuncTable Functions;
00086
00087 inline static void
00088 defineInternal(const char* name,SeExprFunc f)
00089 {
00090
00091
00092 Functions.define(name,f);
00093 }
00094
00095 inline static void
00096 defineInternal3(const char* name,SeExprFunc f,const char* docString)
00097 {
00098
00099
00100 Functions.define(name,f,docString);
00101 }
00102
00103 void FuncTable::initIfNeeded(){
00104
00105
00106 if(_inited) return;
00107 _inited=true;
00108
00109
00110 SeExpr::defineBuiltins(defineInternal,defineInternal3);
00111 const char* path = getenv("SE_EXPR_PLUGINS");
00112 if (path) SeExprFunc::loadPlugins(path);
00113
00114 }
00115
00116 }
00117
00118
00119 bool SeExprFuncX::prep(SeExprFuncNode* node, bool wantVec)
00120 {
00121
00122
00123
00124 return node->SeExprNode::prep(wantVec);
00125 }
00126
00127
00128 static SeExprInternal::Mutex mutex;
00129
00130 void SeExprFunc::init()
00131 {
00132 SeExprInternal::AutoMutex locker(mutex);
00133 Functions.initIfNeeded();
00134 }
00135
00136 const SeExprFunc*
00137 SeExprFunc::lookup(const std::string& name)
00138 {
00139 mutex.lock();
00140 Functions.initIfNeeded();
00141 const SeExprFunc* ret=Functions.lookup(name);
00142 mutex.unlock();
00143 return ret;
00144 }
00145
00146
00147 void
00148 SeExprFunc::define(const char* name, SeExprFunc f)
00149 {
00150 mutex.lock();
00151 Functions.initIfNeeded();
00152 defineInternal(name,f);
00153 mutex.unlock();
00154 }
00155
00156 void
00157 SeExprFunc::define(const char* name, SeExprFunc f,const char* docString)
00158 {
00159 mutex.lock();
00160 Functions.initIfNeeded();
00161 defineInternal3(name,f,docString);
00162 mutex.unlock();
00163 }
00164
00165 void
00166 SeExprFunc::getFunctionNames(std::vector<std::string>& names)
00167 {
00168 mutex.lock();
00169 Functions.initIfNeeded();
00170 Functions.getFunctionNames(names);
00171 mutex.unlock();
00172 }
00173
00174 std::string
00175 SeExprFunc::getDocString(const char* functionName)
00176 {
00177 mutex.lock();
00178 Functions.initIfNeeded();
00179 std::string ret=Functions.getDocString(functionName);
00180 mutex.unlock();
00181 return ret;
00182 }
00183
00184 #ifndef SEEXPR_WIN32
00185
00186 #ifdef __APPLE__
00187 static int MatchPluginName(struct dirent* dir)
00188 #else
00189 static int MatchPluginName(const struct dirent* dir)
00190 #endif
00191 {
00192 const char* name = dir->d_name;
00193
00194 return
00195 !strncmp(name, "SeExpr", 6) &&
00196 !strcmp(name + strlen(name) - 3, ".so");
00197 }
00198 #endif
00199
00200
00201 void
00202 SeExprFunc::loadPlugins(const char* path)
00203 {
00204 #ifdef SEEXPR_WIN32
00205
00206 #else
00207
00208 char* pathdup = strdup(path);
00209 char* state = 0;
00210 char* entry = strtok_r(pathdup, ":", &state);
00211 while (entry) {
00212
00213 if ((!strcmp(entry+strlen(entry)-3, ".so")))
00214 loadPlugin(entry);
00215 else {
00216
00217 struct dirent** matches = 0;
00218 int numMatches = scandir(entry, &matches, MatchPluginName, alphasort);
00219 for (int i = 0; i < numMatches; i++) {
00220 std::string fullpath = entry; fullpath += "/";
00221 fullpath += matches[i]->d_name;
00222 loadPlugin(fullpath.c_str());
00223 free(matches[i]);
00224 }
00225 if (matches) free(matches);
00226 else {
00227 std::cerr << "No plugins found matching "
00228 << path << "/SeExpr*.so" << std::endl;
00229 }
00230 }
00231
00232 entry = strtok_r(0, ":", &state);
00233 }
00234 free(pathdup);
00235 #endif
00236 }
00237
00238 void
00239 SeExprFunc::loadPlugin(const char* path)
00240 {
00241 #ifdef SEEXPR_WIN32
00242 std::cerr<<"SeExpr: warning Plugins are not supported on windows currently"<<std::endl;
00243 #else
00244 void* handle = dlopen(path, RTLD_LAZY);
00245 if (!handle) {
00246 std::cerr << "Error reading expression plugin: " << path << std::endl;
00247 const char* err = dlerror();
00248 if (err) std::cerr << err << std::endl;
00249 return;
00250 }
00251 typedef void (*initfn_v1) (SeExprFunc::Define);
00252 initfn_v1 init_v1 = (initfn_v1) dlsym(handle, "SeExprPluginInit");
00253 typedef void (*initfn_v2) (SeExprFunc::Define3);
00254 initfn_v2 init_v2 = (initfn_v2) dlsym(handle, "SeExprPluginInitV2");
00255
00256 if(init_v2){
00257 init_v2(defineInternal3);
00258 Functions.addLibraryReference(handle);
00259 }else if(init_v1){
00260 init_v1(defineInternal);
00261 Functions.addLibraryReference(handle);
00262 }else{
00263 std::cerr << "Error reading expression plugin: " << path << std::endl;
00264 std::cerr << "No function named SeExprPluginInit or SeExprPluginInitV2 found" << std::endl;
00265 dlclose(handle);
00266 return;
00267 }
00268 #endif
00269 }
00270