5 #include <boost/filesystem.hpp>
7 #include "vxlibrary.hpp"
9 #define IMPORTHOOK_NAME "importhook"
12 #define IMPORT_GET_SELF(__vm__, __var__) \
14 if(!__vm__->GetRegistryTable()->Get(v->NewString(IMPORTHOOK_NAME), o)) \
16 return v->ThrowError("importhook wasn't installed correctly!"); \
18 __var__ = (VXImportHook*)o.UserPointer();
20 namespace fslib
= boost::filesystem
;
21 typedef fslib::filesystem_error fslib_error
;
24 //DSO_EXT = kernel.getproperty("DSO_EXT")
25 //const char* DSO_EXT = "." VOX_PLATFORM_NAME ".vxd";
26 const char* DSO_EXT
= ".vxd";
27 //VOX_EXT = kernel.getproperty("VOX_EXT")
28 const char* VOX_EXT
= ".vx";
30 const char* VOX_PLUGIN_FUNCTION_OPEN
= "vox_module_open";
32 void get_err(VXState
* v
, const char** err
)
36 if(VX_FAILED(vox_getstring(v, -1, err, NULL)))
38 *err = "<unknown error>";
41 (*err
) = v
->LastError();
50 bool dll_failed_to_load
;
55 VXSharedLibrary handle
;
61 VXVector
<std::string
> searchpaths
;
62 VXVector
<VXImportError
> errvalues
;
66 void fill_searchpaths()
68 const char* env
= getenv("VOX_PATH");
71 searchpaths
.push_back(env
);
73 searchpaths
.push_back("./");
74 // add installdir before srcdir, so it has higher priority
75 #if defined(VOX_MODULEPATH_INSTALLDIR)
76 searchpaths
.push_back(VOX_MODULEPATH_INSTALLDIR
);
78 #if defined(VOX_MODULEPATH_SRCDIR)
79 searchpaths
.push_back(VOX_MODULEPATH_SRCDIR
);
83 VXImportHook(VXState
* _v
): v(_v
)
88 void pusherror(const std::string
& path
,
89 const std::string
& message
,
91 bool dll_failed_to_load
= false)
95 err
.message
= message
;
97 err
.dll_failed_to_load
= dll_failed_to_load
;
98 errvalues
.push_back(err
);
101 void do_import(const std::string
& expr
)
108 std::string searchpath
;
111 this->foundmodule
= false;
112 for(i
=0; i
<searchpaths
.size(); i
++)
114 searchpath
= searchpaths
.at(i
);
116 fslib::path
p(searchpath
);
119 abspath
= searchpath
+ relpath
;
123 abspath
= abspath
+ searchpath
+ relpath
;
125 this->checkmodule(abspath
);
126 if(foundmodule
== true)
131 if(foundmodule
== false)
133 // create a little errormessage, explaining what went wrong,
134 // and what files we have searched
135 // yes, the errormessage is inspired by Lua
137 msg
= "import: Module '"+expr
+"' not found:\n";
138 for(i
=0; i
<errvalues
.size(); i
++)
140 pair
= errvalues
.at(i
);
141 std::string epath
= pair
.path
;
142 std::string eerr
= pair
.message
;
143 // might happen in some rare cases
144 if(eerr
.length() == 0)
148 //if(pair.is_dll && pair.dll_failed_to_load)
150 // msg += " No file '"+epath+"' ("+eerr+")\n";
154 msg
+= " No file '"+epath
+"'\n";
157 status
= v
->ThrowError(msg
.c_str());
162 void checkmodule(const std::string
& abspath
)
164 std::string dso_path
;
165 std::string vox_path
;
167 dso_path
= abspath
+ DSO_EXT
;
168 vox_path
= abspath
+ VOX_EXT
;
169 this->check_voxfile(vox_path
);
170 // only continue searching DSO files when
171 // no voxfile could be found, to
172 // prevent race conditions
175 this->check_dsofile(dso_path
);
179 void check_voxfile(const std::string
& path
)
186 if(VX_SUCCEEDED(v
->LoadFile(path
.c_str(), true, &ofail
, &closure
)))
189 if(VX_SUCCEEDED(v
->CallSimple(closure
, 1, retval
, true)))
198 pusherror(path
, ret_err
);
207 pusherror(path
, ret_err
);
212 void check_dsofile(const std::string
& path
)
218 lib
.handle
.open(path
);
219 func
= lib
.handle
.resolve
<VXFunction
>(VOX_PLUGIN_FUNCTION_OPEN
);
224 catch(VXSharedLibrary::LoadError
& err
)
227 pusherror(path
, err
.what(), true, true);
229 catch(std::runtime_error
& err
)
231 lib
.handle
.destroy();
232 pusherror(path
, err
.what(), true, true);
238 this->errvalues
.clear();
245 VXInteger
importreg_release(VXState
* v
)
248 IMPORT_GET_SELF(v
, self
)
254 VXInteger
importlib_import(VXState
* v
)
258 IMPORT_GET_SELF(v
, self
)
259 v
->GetString(2, &expr
);
260 self
->do_import(expr
);
261 return self
->finalize();
264 VXInteger
package_searchpaths(VXState
* v
)
269 IMPORT_GET_SELF(v
, self
)
270 VXArrayObj
* arr
= v
->NewArray();
271 for(i
=0; i
<self
->searchpaths
.size(); i
++)
273 path
= self
->searchpaths
.at(i
);
274 arr
->Append(v
->NewString(path
.c_str(), path
.length()));
280 VXInteger
package_addpath(VXState
* v
)
284 IMPORT_GET_SELF(v
, self
)
285 v
->GetString(2, &path
);
286 self
->searchpaths
.push_back(path
);
290 static VXRegFunction package_funcs
[] =
292 {"searchpaths", package_searchpaths
, 1, NULL
},
293 {"addpath", package_addpath
, 2, ".s"},
297 static VXRegFunction importlib_funcs
[]=
299 {"import", importlib_import
, 2, ".s"},
304 VXInteger
voxstd_register_importlib(VXState
* v
)
306 VXImportHook
* self
= new VXImportHook(v
);
307 v
->GetRegistryTable()->NewSlot(v
->NewString(IMPORTHOOK_NAME
), (VXUserPointer
)self
);
308 //vox_pushatexitfunc_native(v, importreg_release);
309 v
->AtExit(v
->NewClosure(importreg_release
, 0));
310 //vox_registerlib(v, "package", package_funcs, true, true);
311 v
->RegisterLib("package", package_funcs
, true);
312 //vox_registerlib(v, NULL, importlib_funcs, true, true);
313 v
->RegisterLib(NULL
, importlib_funcs
, true);