diff options
author | Mike Pall <mike> | 2011-08-17 00:10:12 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2011-08-17 00:10:12 +0200 |
commit | aad7ea3c02b0baed5b700565eea36c9b33d7c6b1 (patch) | |
tree | 128a3d419820cc65c9e83de84dc9c4745bf4b083 /src/lib_package.c | |
parent | b500b50edc0d421e72a1126620fbe99e822d05ba (diff) | |
download | luajit-aad7ea3c02b0baed5b700565eea36c9b33d7c6b1.tar.gz luajit-aad7ea3c02b0baed5b700565eea36c9b33d7c6b1.tar.bz2 luajit-aad7ea3c02b0baed5b700565eea36c9b33d7c6b1.zip |
Load embedded bytecode with require().
Diffstat (limited to 'src/lib_package.c')
-rw-r--r-- | src/lib_package.c | 106 |
1 files changed, 81 insertions, 25 deletions
diff --git a/src/lib_package.c b/src/lib_package.c index 71e0826b..cb5f64e7 100644 --- a/src/lib_package.c +++ b/src/lib_package.c | |||
@@ -22,11 +22,16 @@ | |||
22 | /* Error codes for ll_loadfunc. */ | 22 | /* Error codes for ll_loadfunc. */ |
23 | #define PACKAGE_ERR_LIB 1 | 23 | #define PACKAGE_ERR_LIB 1 |
24 | #define PACKAGE_ERR_FUNC 2 | 24 | #define PACKAGE_ERR_FUNC 2 |
25 | #define PACKAGE_ERR_LOAD 3 | ||
25 | 26 | ||
26 | /* Redefined in platform specific part. */ | 27 | /* Redefined in platform specific part. */ |
27 | #define PACKAGE_LIB_FAIL "open" | 28 | #define PACKAGE_LIB_FAIL "open" |
28 | #define setprogdir(L) ((void)0) | 29 | #define setprogdir(L) ((void)0) |
29 | 30 | ||
31 | /* Symbol name prefixes. */ | ||
32 | #define SYMPREFIX_CF "luaopen_%s" | ||
33 | #define SYMPREFIX_BC "luaJIT_BC_%s" | ||
34 | |||
30 | #if LJ_TARGET_DLOPEN | 35 | #if LJ_TARGET_DLOPEN |
31 | 36 | ||
32 | #include <dlfcn.h> | 37 | #include <dlfcn.h> |
@@ -50,11 +55,29 @@ static lua_CFunction ll_sym(lua_State *L, void *lib, const char *sym) | |||
50 | return f; | 55 | return f; |
51 | } | 56 | } |
52 | 57 | ||
58 | static const char *ll_bcsym(void *lib, const char *sym) | ||
59 | { | ||
60 | #if defined(RTLD_DEFAULT) | ||
61 | if (lib == NULL) lib = RTLD_DEFAULT; | ||
62 | #elif LJ_TARGET_OSX || LJ_TARGET_BSD | ||
63 | if (lib == NULL) lib = (void *)(intptr_t)-2; | ||
64 | #endif | ||
65 | return (const char *)dlsym(lib, sym); | ||
66 | } | ||
67 | |||
53 | #elif LJ_TARGET_WINDOWS | 68 | #elif LJ_TARGET_WINDOWS |
54 | 69 | ||
55 | #define WIN32_LEAN_AND_MEAN | 70 | #define WIN32_LEAN_AND_MEAN |
71 | #ifndef WINVER | ||
72 | #define WINVER 0x0500 | ||
73 | #endif | ||
56 | #include <windows.h> | 74 | #include <windows.h> |
57 | 75 | ||
76 | #ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | ||
77 | #define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 4 | ||
78 | BOOL WINAPI GetModuleHandleExA(DWORD, LPCSTR, HMODULE*); | ||
79 | #endif | ||
80 | |||
58 | #undef setprogdir | 81 | #undef setprogdir |
59 | 82 | ||
60 | static void setprogdir(lua_State *L) | 83 | static void setprogdir(lua_State *L) |
@@ -102,6 +125,20 @@ static lua_CFunction ll_sym(lua_State *L, void *lib, const char *sym) | |||
102 | return f; | 125 | return f; |
103 | } | 126 | } |
104 | 127 | ||
128 | static const char *ll_bcsym(void *lib, const char *sym) | ||
129 | { | ||
130 | if (lib) { | ||
131 | return (const char *)GetProcAddress((HINSTANCE)lib, sym); | ||
132 | } else { | ||
133 | HINSTANCE h = GetModuleHandle(NULL); | ||
134 | const char *p = (const char *)GetProcAddress(h, sym); | ||
135 | if (p == NULL && GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, | ||
136 | (const char *)ll_bcsym, &h)) | ||
137 | p = (const char *)GetProcAddress(h, sym); | ||
138 | return p; | ||
139 | } | ||
140 | } | ||
141 | |||
105 | #else | 142 | #else |
106 | 143 | ||
107 | #undef PACKAGE_LIB_FAIL | 144 | #undef PACKAGE_LIB_FAIL |
@@ -127,6 +164,13 @@ static lua_CFunction ll_sym(lua_State *L, void *lib, const char *sym) | |||
127 | lua_pushliteral(L, DLMSG); | 164 | lua_pushliteral(L, DLMSG); |
128 | return NULL; | 165 | return NULL; |
129 | } | 166 | } |
167 | |||
168 | static const char *ll_bcsym(void *lib, const char *sym) | ||
169 | { | ||
170 | (void)lib; (void)sym; | ||
171 | return NULL; | ||
172 | } | ||
173 | |||
130 | #endif | 174 | #endif |
131 | 175 | ||
132 | /* ------------------------------------------------------------------------ */ | 176 | /* ------------------------------------------------------------------------ */ |
@@ -151,18 +195,41 @@ static void **ll_register(lua_State *L, const char *path) | |||
151 | return plib; | 195 | return plib; |
152 | } | 196 | } |
153 | 197 | ||
154 | static int ll_loadfunc(lua_State *L, const char *path, const char *sym) | 198 | static const char *mksymname(lua_State *L, const char *modname, |
199 | const char *prefix) | ||
200 | { | ||
201 | const char *funcname; | ||
202 | const char *mark = strchr(modname, *LUA_IGMARK); | ||
203 | if (mark) modname = mark + 1; | ||
204 | funcname = luaL_gsub(L, modname, ".", "_"); | ||
205 | funcname = lua_pushfstring(L, prefix, funcname); | ||
206 | lua_remove(L, -2); /* remove 'gsub' result */ | ||
207 | return funcname; | ||
208 | } | ||
209 | |||
210 | static int ll_loadfunc(lua_State *L, const char *path, const char *name, int r) | ||
155 | { | 211 | { |
156 | void **reg = ll_register(L, path); | 212 | void **reg = ll_register(L, path); |
157 | if (*reg == NULL) *reg = ll_load(L, path); | 213 | if (*reg == NULL) *reg = ll_load(L, path); |
158 | if (*reg == NULL) { | 214 | if (*reg == NULL) { |
159 | return PACKAGE_ERR_LIB; /* unable to load library */ | 215 | return PACKAGE_ERR_LIB; /* unable to load library */ |
160 | } else { | 216 | } else { |
217 | const char *sym = r ? name : mksymname(L, name, SYMPREFIX_CF); | ||
161 | lua_CFunction f = ll_sym(L, *reg, sym); | 218 | lua_CFunction f = ll_sym(L, *reg, sym); |
162 | if (f == NULL) | 219 | if (f) { |
163 | return PACKAGE_ERR_FUNC; /* unable to find function */ | 220 | lua_pushcfunction(L, f); |
164 | lua_pushcfunction(L, f); | 221 | return 0; |
165 | return 0; /* return function */ | 222 | } |
223 | if (!r) { | ||
224 | const char *bcdata = ll_bcsym(*reg, mksymname(L, name, SYMPREFIX_BC)); | ||
225 | lua_pop(L, 1); | ||
226 | if (bcdata) { | ||
227 | if (luaL_loadbuffer(L, bcdata, ~(size_t)0, name) != 0) | ||
228 | return PACKAGE_ERR_LOAD; | ||
229 | return 0; | ||
230 | } | ||
231 | } | ||
232 | return PACKAGE_ERR_FUNC; /* unable to find function */ | ||
166 | } | 233 | } |
167 | } | 234 | } |
168 | 235 | ||
@@ -170,7 +237,7 @@ static int lj_cf_package_loadlib(lua_State *L) | |||
170 | { | 237 | { |
171 | const char *path = luaL_checkstring(L, 1); | 238 | const char *path = luaL_checkstring(L, 1); |
172 | const char *init = luaL_checkstring(L, 2); | 239 | const char *init = luaL_checkstring(L, 2); |
173 | int st = ll_loadfunc(L, path, init); | 240 | int st = ll_loadfunc(L, path, init, 1); |
174 | if (st == 0) { /* no errors? */ | 241 | if (st == 0) { /* no errors? */ |
175 | return 1; /* return the loaded function */ | 242 | return 1; /* return the loaded function */ |
176 | } else { /* error; error message is on stack top */ | 243 | } else { /* error; error message is on stack top */ |
@@ -268,32 +335,18 @@ static int lj_cf_package_loader_lua(lua_State *L) | |||
268 | return 1; /* library loaded successfully */ | 335 | return 1; /* library loaded successfully */ |
269 | } | 336 | } |
270 | 337 | ||
271 | static const char *mkfuncname(lua_State *L, const char *modname) | ||
272 | { | ||
273 | const char *funcname; | ||
274 | const char *mark = strchr(modname, *LUA_IGMARK); | ||
275 | if (mark) modname = mark + 1; | ||
276 | funcname = luaL_gsub(L, modname, ".", "_"); | ||
277 | funcname = lua_pushfstring(L, "luaopen_%s", funcname); | ||
278 | lua_remove(L, -2); /* remove 'gsub' result */ | ||
279 | return funcname; | ||
280 | } | ||
281 | |||
282 | static int lj_cf_package_loader_c(lua_State *L) | 338 | static int lj_cf_package_loader_c(lua_State *L) |
283 | { | 339 | { |
284 | const char *funcname; | ||
285 | const char *name = luaL_checkstring(L, 1); | 340 | const char *name = luaL_checkstring(L, 1); |
286 | const char *filename = findfile(L, name, "cpath"); | 341 | const char *filename = findfile(L, name, "cpath"); |
287 | if (filename == NULL) return 1; /* library not found in this path */ | 342 | if (filename == NULL) return 1; /* library not found in this path */ |
288 | funcname = mkfuncname(L, name); | 343 | if (ll_loadfunc(L, filename, name, 0) != 0) |
289 | if (ll_loadfunc(L, filename, funcname) != 0) | ||
290 | loaderror(L, filename); | 344 | loaderror(L, filename); |
291 | return 1; /* library loaded successfully */ | 345 | return 1; /* library loaded successfully */ |
292 | } | 346 | } |
293 | 347 | ||
294 | static int lj_cf_package_loader_croot(lua_State *L) | 348 | static int lj_cf_package_loader_croot(lua_State *L) |
295 | { | 349 | { |
296 | const char *funcname; | ||
297 | const char *filename; | 350 | const char *filename; |
298 | const char *name = luaL_checkstring(L, 1); | 351 | const char *name = luaL_checkstring(L, 1); |
299 | const char *p = strchr(name, '.'); | 352 | const char *p = strchr(name, '.'); |
@@ -302,8 +355,7 @@ static int lj_cf_package_loader_croot(lua_State *L) | |||
302 | lua_pushlstring(L, name, (size_t)(p - name)); | 355 | lua_pushlstring(L, name, (size_t)(p - name)); |
303 | filename = findfile(L, lua_tostring(L, -1), "cpath"); | 356 | filename = findfile(L, lua_tostring(L, -1), "cpath"); |
304 | if (filename == NULL) return 1; /* root not found */ | 357 | if (filename == NULL) return 1; /* root not found */ |
305 | funcname = mkfuncname(L, name); | 358 | if ((st = ll_loadfunc(L, filename, name, 0)) != 0) { |
306 | if ((st = ll_loadfunc(L, filename, funcname)) != 0) { | ||
307 | if (st != PACKAGE_ERR_FUNC) loaderror(L, filename); /* real error */ | 359 | if (st != PACKAGE_ERR_FUNC) loaderror(L, filename); /* real error */ |
308 | lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS, | 360 | lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS, |
309 | name, filename); | 361 | name, filename); |
@@ -319,8 +371,12 @@ static int lj_cf_package_loader_preload(lua_State *L) | |||
319 | if (!lua_istable(L, -1)) | 371 | if (!lua_istable(L, -1)) |
320 | luaL_error(L, LUA_QL("package.preload") " must be a table"); | 372 | luaL_error(L, LUA_QL("package.preload") " must be a table"); |
321 | lua_getfield(L, -1, name); | 373 | lua_getfield(L, -1, name); |
322 | if (lua_isnil(L, -1)) /* not found? */ | 374 | if (lua_isnil(L, -1)) { /* Not found? */ |
323 | lua_pushfstring(L, "\n\tno field package.preload['%s']", name); | 375 | const char *bcname = mksymname(L, name, SYMPREFIX_BC); |
376 | const char *bcdata = ll_bcsym(NULL, bcname); | ||
377 | if (bcdata == NULL || luaL_loadbuffer(L, bcdata, ~(size_t)0, name) != 0) | ||
378 | lua_pushfstring(L, "\n\tno field package.preload['%s']", name); | ||
379 | } | ||
324 | return 1; | 380 | return 1; |
325 | } | 381 | } |
326 | 382 | ||