diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2004-12-22 15:43:27 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2004-12-22 15:43:27 -0200 |
| commit | 96727c61b87d199b51a3ebb707255e79d5ed1b84 (patch) | |
| tree | c99da1452411280bb649910908ac58a32df93197 /loadlib.c | |
| parent | d5ebc3ff6de4b5f7019bb887e917e00cb3a0a899 (diff) | |
| download | lua-96727c61b87d199b51a3ebb707255e79d5ed1b84.tar.gz lua-96727c61b87d199b51a3ebb707255e79d5ed1b84.tar.bz2 lua-96727c61b87d199b51a3ebb707255e79d5ed1b84.zip | |
several improvements/corrections
Diffstat (limited to 'loadlib.c')
| -rw-r--r-- | loadlib.c | 173 |
1 files changed, 84 insertions, 89 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: loadlib.c,v 1.11 2004/11/19 15:52:12 roberto Exp roberto $ | 2 | ** $Id: loadlib.c,v 1.12 2004/12/13 12:14:21 roberto Exp roberto $ |
| 3 | ** Dynamic library loader for Lua | 3 | ** Dynamic library loader for Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | * | 5 | * |
| @@ -58,26 +58,23 @@ static void registerlib (lua_State *L, const void *lib); | |||
| 58 | 58 | ||
| 59 | #define freelib dlclose | 59 | #define freelib dlclose |
| 60 | 60 | ||
| 61 | static int loadlib(lua_State *L, const char *path, const char *init) | 61 | static int loadlib(lua_State *L, const char *path, const char *init) { |
| 62 | { | 62 | void *lib=dlopen(path,RTLD_NOW); |
| 63 | void *lib=dlopen(path,RTLD_NOW); | 63 | if (lib != NULL) { |
| 64 | if (lib!=NULL) | 64 | lua_CFunction f=(lua_CFunction) dlsym(lib,init); |
| 65 | { | 65 | if (f != NULL) { |
| 66 | lua_CFunction f=(lua_CFunction) dlsym(lib,init); | 66 | registerlib(L, lib); |
| 67 | if (f!=NULL) | 67 | lua_pushcfunction(L,f); |
| 68 | { | 68 | return 0; |
| 69 | registerlib(L, lib); | 69 | } |
| 70 | lua_pushcfunction(L,f); | 70 | } |
| 71 | return 0; | 71 | /* else return appropriate error message */ |
| 72 | } | 72 | lua_pushstring(L,dlerror()); |
| 73 | } | 73 | if (lib != NULL) { |
| 74 | /* else return appropriate error message */ | 74 | dlclose(lib); |
| 75 | lua_pushstring(L,dlerror()); | 75 | return ERR_FUNCTION; /* error loading function */ |
| 76 | if (lib!=NULL) { | 76 | } |
| 77 | dlclose(lib); | 77 | else return ERR_OPEN; /* error loading library */ |
| 78 | return ERR_FUNCTION; /* error loading function */ | ||
| 79 | } | ||
| 80 | else return ERR_OPEN; /* error loading library */ | ||
| 81 | } | 78 | } |
| 82 | 79 | ||
| 83 | 80 | ||
| @@ -91,36 +88,34 @@ static int loadlib(lua_State *L, const char *path, const char *init) | |||
| 91 | 88 | ||
| 92 | #define freelib(lib) FreeLibrary((HINSTANCE)lib) | 89 | #define freelib(lib) FreeLibrary((HINSTANCE)lib) |
| 93 | 90 | ||
| 94 | static void pusherror(lua_State *L) | 91 | |
| 95 | { | 92 | static void pusherror(lua_State *L) { |
| 96 | int error=GetLastError(); | 93 | int error = GetLastError(); |
| 97 | char buffer[128]; | 94 | char buffer[128]; |
| 98 | if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, | 95 | if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, |
| 99 | 0, error, 0, buffer, sizeof(buffer), 0)) | 96 | 0, error, 0, buffer, sizeof(buffer), 0)) |
| 100 | lua_pushstring(L,buffer); | 97 | lua_pushstring(L,buffer); |
| 101 | else | 98 | else |
| 102 | lua_pushfstring(L,"system error %d\n",error); | 99 | lua_pushfstring(L, "system error %d\n", error); |
| 103 | } | 100 | } |
| 104 | 101 | ||
| 105 | static int loadlib(lua_State *L, const char *path, const char *init) | 102 | |
| 106 | { | 103 | static int loadlib (lua_State *L, const char *path, const char *init) { |
| 107 | HINSTANCE lib=LoadLibrary(path); | 104 | HINSTANCE lib = LoadLibrary(path); |
| 108 | if (lib!=NULL) | 105 | if (lib != NULL) { |
| 109 | { | 106 | lua_CFunction f = (lua_CFunction)GetProcAddress(lib, init); |
| 110 | lua_CFunction f=(lua_CFunction) GetProcAddress(lib,init); | 107 | if (f != NULL) { |
| 111 | if (f!=NULL) | 108 | registerlib(L, lib); |
| 112 | { | 109 | lua_pushcfunction(L, f); |
| 113 | registerlib(L, lib); | 110 | return 0; |
| 114 | lua_pushcfunction(L,f); | 111 | } |
| 115 | return 1; | ||
| 116 | } | 112 | } |
| 117 | } | 113 | pusherror(L); |
| 118 | pusherror(L); | 114 | if (lib != NULL) { |
| 119 | if (lib!=NULL) { | 115 | FreeLibrary(lib); |
| 120 | FreeLibrary(lib); | 116 | return ERR_OPEN; |
| 121 | return ERR_OPEN; | 117 | } |
| 122 | } | 118 | else return ERR_FUNCTION; |
| 123 | else return ERR_FUNCTION; | ||
| 124 | } | 119 | } |
| 125 | 120 | ||
| 126 | 121 | ||
| @@ -134,21 +129,22 @@ static int loadlib(lua_State *L, const char *path, const char *init) | |||
| 134 | /* Mach cannot unload images (?) */ | 129 | /* Mach cannot unload images (?) */ |
| 135 | #define freelib(lib) ((void)lib) | 130 | #define freelib(lib) ((void)lib) |
| 136 | 131 | ||
| 137 | static void pusherror (lua_State *L) | 132 | |
| 138 | { | 133 | static void pusherror (lua_State *L) { |
| 139 | const char *err_str; | 134 | const char *err_str; |
| 140 | const char *err_file; | 135 | const char *err_file; |
| 141 | NSLinkEditErrors err; | 136 | NSLinkEditErrors err; |
| 142 | int err_num; | 137 | int err_num; |
| 143 | NSLinkEditError(&err, &err_num, &err_file, &err_str); | 138 | NSLinkEditError(&err, &err_num, &err_file, &err_str); |
| 144 | lua_pushstring(L, err_str); | 139 | lua_pushstring(L, err_str); |
| 145 | } | 140 | } |
| 146 | 141 | ||
| 142 | |||
| 147 | static int loadlib (lua_State *L, const char *path, const char *init) { | 143 | static int loadlib (lua_State *L, const char *path, const char *init) { |
| 148 | const struct mach_header *lib; | 144 | const struct mach_header *lib; |
| 149 | /* this would be a rare case, but prevents crashing if it happens */ | 145 | /* this would be a rare case, but prevents crashing if it happens */ |
| 150 | if(!_dyld_present()) { | 146 | if(!_dyld_present()) { |
| 151 | lua_pushstring(L,"dyld not present."); | 147 | lua_pushstring(L, "dyld not present."); |
| 152 | return ERR_OPEN; | 148 | return ERR_OPEN; |
| 153 | } | 149 | } |
| 154 | lib = NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR); | 150 | lib = NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR); |
| @@ -159,7 +155,7 @@ static int loadlib (lua_State *L, const char *path, const char *init) { | |||
| 159 | if(init_sym != NULL) { | 155 | if(init_sym != NULL) { |
| 160 | lua_CFunction f = (lua_CFunction)NSAddressOfSymbol(init_sym); | 156 | lua_CFunction f = (lua_CFunction)NSAddressOfSymbol(init_sym); |
| 161 | registerlib(L, lib); | 157 | registerlib(L, lib); |
| 162 | lua_pushcfunction(L,f); | 158 | lua_pushcfunction(L, f); |
| 163 | return 0; | 159 | return 0; |
| 164 | } | 160 | } |
| 165 | } | 161 | } |
| @@ -177,11 +173,10 @@ static int loadlib (lua_State *L, const char *path, const char *init) { | |||
| 177 | 173 | ||
| 178 | #define freelib(lib) ((void)lib) | 174 | #define freelib(lib) ((void)lib) |
| 179 | 175 | ||
| 180 | static int loadlib(lua_State *L, const char *path, const char *init) | 176 | static int loadlib (lua_State *L, const char *path, const char *init) { |
| 181 | { | 177 | (void)path; (void)init; (void)®isterlib; /* to avoid warnings */ |
| 182 | (void)path; (void)init; (void)®isterlib; /* to avoid warnings */ | 178 | lua_pushliteral(L,"`loadlib' not supported"); |
| 183 | lua_pushliteral(L,"`loadlib' not supported"); | 179 | return ERR_ABSENT; |
| 184 | return ERR_ABSENT; | ||
| 185 | } | 180 | } |
| 186 | 181 | ||
| 187 | #endif | 182 | #endif |
| @@ -192,41 +187,39 @@ static int loadlib(lua_State *L, const char *path, const char *init) | |||
| 192 | ** so that, when Lua closes its state, the library's __gc metamethod | 187 | ** so that, when Lua closes its state, the library's __gc metamethod |
| 193 | ** will be called to unload the library. | 188 | ** will be called to unload the library. |
| 194 | */ | 189 | */ |
| 195 | static void registerlib (lua_State *L, const void *lib) | 190 | static void registerlib (lua_State *L, const void *lib) { |
| 196 | { | 191 | const void **plib = (const void **)lua_newuserdata(L, sizeof(const void *)); |
| 197 | const void **plib = (const void **)lua_newuserdata(L, sizeof(const void *)); | 192 | *plib = lib; |
| 198 | *plib = lib; | 193 | luaL_getmetatable(L, "_LOADLIB"); |
| 199 | luaL_getmetatable(L, "_LOADLIB"); | 194 | lua_setmetatable(L, -2); |
| 200 | lua_setmetatable(L, -2); | 195 | lua_pushboolean(L, 1); |
| 201 | lua_pushboolean(L, 1); | 196 | lua_settable(L, LUA_REGISTRYINDEX); /* registry[lib] = true */ |
| 202 | lua_settable(L, LUA_REGISTRYINDEX); /* registry[lib] = true */ | ||
| 203 | } | 197 | } |
| 204 | 198 | ||
| 205 | /* | 199 | /* |
| 206 | ** __gc tag method: calls library's `freelib' function with the lib | 200 | ** __gc tag method: calls library's `freelib' function with the lib |
| 207 | ** handle | 201 | ** handle |
| 208 | */ | 202 | */ |
| 209 | static int gctm (lua_State *L) | 203 | static int gctm (lua_State *L) { |
| 210 | { | 204 | void *lib = *(void **)luaL_checkudata(L, 1, "_LOADLIB"); |
| 211 | void *lib = *(void **)luaL_checkudata(L, 1, "_LOADLIB"); | 205 | freelib(lib); |
| 212 | freelib(lib); | 206 | return 0; |
| 213 | return 0; | ||
| 214 | } | 207 | } |
| 215 | 208 | ||
| 216 | 209 | ||
| 217 | static int ll_loadlib (lua_State *L) { | 210 | static int ll_loadlib (lua_State *L) { |
| 218 | static const char *const errcodes[] = {NULL, "open", "init", "absent"}; | 211 | static const char *const errcodes[] = {NULL, "open", "init", "absent"}; |
| 219 | const char *path=luaL_checkstring(L,1); | 212 | const char *path = luaL_checkstring(L, 1); |
| 220 | const char *init=luaL_checkstring(L,2); | 213 | const char *init = luaL_checkstring(L, 2); |
| 221 | int res = loadlib(L,path,init); | 214 | int res = loadlib(L,path,init); |
| 222 | if (res == 0) /* no error? */ | 215 | if (res == 0) /* no error? */ |
| 223 | return 1; /* function is at stack top */ | 216 | return 1; /* function is at stack top */ |
| 224 | else { /* error */ | 217 | else { /* error */ |
| 225 | lua_pushnil(L); | 218 | lua_pushnil(L); |
| 226 | lua_insert(L,-2); /* insert nil before error message */ | 219 | lua_insert(L, -2); /* insert nil before error message */ |
| 227 | lua_pushstring(L, errcodes[res]); | 220 | lua_pushstring(L, errcodes[res]); |
| 228 | return 3; | 221 | return 3; |
| 229 | } | 222 | } |
| 230 | } | 223 | } |
| 231 | 224 | ||
| 232 | 225 | ||
| @@ -264,7 +257,7 @@ static const char *loadC (lua_State *L, const char *fname, const char *name) { | |||
| 264 | luaL_getfield(L, LUA_GLOBALSINDEX, "package.cpath"); | 257 | luaL_getfield(L, LUA_GLOBALSINDEX, "package.cpath"); |
| 265 | path = lua_tostring(L, -1); | 258 | path = lua_tostring(L, -1); |
| 266 | if (path == NULL) | 259 | if (path == NULL) |
| 267 | luaL_error(L, "global _CPATH must be a string"); | 260 | luaL_error(L, "`package.cpath' must be a string"); |
| 268 | fname = luaL_searchpath(L, fname, path); | 261 | fname = luaL_searchpath(L, fname, path); |
| 269 | if (fname == NULL) return path; /* library not found in this path */ | 262 | if (fname == NULL) return path; /* library not found in this path */ |
| 270 | funcname = luaL_gsub(L, name, ".", LUA_OFSEP); | 263 | funcname = luaL_gsub(L, name, ".", LUA_OFSEP); |
| @@ -346,6 +339,8 @@ static int ll_module (lua_State *L) { | |||
| 346 | lua_pushvalue(L, LUA_GLOBALSINDEX); | 339 | lua_pushvalue(L, LUA_GLOBALSINDEX); |
| 347 | lua_setfield(L, -2, "__index"); /* mt.__index = _G */ | 340 | lua_setfield(L, -2, "__index"); /* mt.__index = _G */ |
| 348 | lua_setmetatable(L, -2); | 341 | lua_setmetatable(L, -2); |
| 342 | lua_pushvalue(L, -1); | ||
| 343 | lua_setfield(L, -2, "_M"); /* module._M = module */ | ||
| 349 | lua_pushstring(L, modname); | 344 | lua_pushstring(L, modname); |
| 350 | lua_setfield(L, -2, "_NAME"); | 345 | lua_setfield(L, -2, "_NAME"); |
| 351 | dot = strrchr(modname, '.'); /* look for last dot in module name */ | 346 | dot = strrchr(modname, '.'); /* look for last dot in module name */ |
