00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <stdlib.h>
00013 #include <string.h>
00014
00015
00016 #define loadlib_c
00017 #define LUA_LIB
00018
00019 #include "lua.h"
00020
00021 #include "lauxlib.h"
00022 #include "lualib.h"
00023
00024
00025
00026 #define LUA_POF "luaopen_"
00027
00028
00029 #define LUA_OFSEP "_"
00030
00031
00032 #define LIBPREFIX "LOADLIB: "
00033
00034 #define POF LUA_POF
00035 #define LIB_FAIL "open"
00036
00037
00038
00039 #define ERRLIB 1
00040 #define ERRFUNC 2
00041
00042 #define setprogdir(L) ((void)0)
00043
00044
00045 static void ll_unloadlib (void *lib);
00046 static void *ll_load (lua_State *L, const char *path);
00047 static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym);
00048
00049
00050
00051 #if defined(LUA_DL_DLOPEN)
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 #include <dlfcn.h>
00062
00063 static void ll_unloadlib (void *lib) {
00064 dlclose(lib);
00065 }
00066
00067
00068 static void *ll_load (lua_State *L, const char *path) {
00069 void *lib = dlopen(path, RTLD_NOW);
00070 if (lib == NULL) lua_pushstring(L, dlerror());
00071 return lib;
00072 }
00073
00074
00075 static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
00076 lua_CFunction f = (lua_CFunction)dlsym(lib, sym);
00077 if (f == NULL) lua_pushstring(L, dlerror());
00078 return f;
00079 }
00080
00081
00082
00083
00084
00085 #elif defined(LUA_DL_DLL)
00086
00087
00088
00089
00090
00091
00092 #include <windows.h>
00093
00094
00095 #undef setprogdir
00096
00097 static void setprogdir (lua_State *L) {
00098 char buff[MAX_PATH + 1];
00099 char *lb;
00100 DWORD nsize = sizeof(buff)/sizeof(char);
00101 DWORD n = GetModuleFileNameA(NULL, buff, nsize);
00102 if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL)
00103 luaL_error(L, "unable to get ModuleFileName");
00104 else {
00105 *lb = '\0';
00106 luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff);
00107 lua_remove(L, -2);
00108 }
00109 }
00110
00111
00112 static void pusherror (lua_State *L) {
00113 int error = GetLastError();
00114 char buffer[128];
00115 if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
00116 NULL, error, 0, buffer, sizeof(buffer), NULL))
00117 lua_pushstring(L, buffer);
00118 else
00119 lua_pushfstring(L, "system error %d\n", error);
00120 }
00121
00122 static void ll_unloadlib (void *lib) {
00123 FreeLibrary((HINSTANCE)lib);
00124 }
00125
00126
00127 static void *ll_load (lua_State *L, const char *path) {
00128 HINSTANCE lib = LoadLibraryA(path);
00129 if (lib == NULL) pusherror(L);
00130 return lib;
00131 }
00132
00133
00134 static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
00135 lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym);
00136 if (f == NULL) pusherror(L);
00137 return f;
00138 }
00139
00140
00141
00142
00143
00144 #elif defined(LUA_DL_DYLD)
00145
00146
00147
00148
00149
00150
00151 #include <mach-o/dyld.h>
00152
00153
00154
00155 #undef POF
00156 #define POF "_" LUA_POF
00157
00158
00159 static void pusherror (lua_State *L) {
00160 const char *err_str;
00161 const char *err_file;
00162 NSLinkEditErrors err;
00163 int err_num;
00164 NSLinkEditError(&err, &err_num, &err_file, &err_str);
00165 lua_pushstring(L, err_str);
00166 }
00167
00168
00169 static const char *errorfromcode (NSObjectFileImageReturnCode ret) {
00170 switch (ret) {
00171 case NSObjectFileImageInappropriateFile:
00172 return "file is not a bundle";
00173 case NSObjectFileImageArch:
00174 return "library is for wrong CPU type";
00175 case NSObjectFileImageFormat:
00176 return "bad format";
00177 case NSObjectFileImageAccess:
00178 return "cannot access file";
00179 case NSObjectFileImageFailure:
00180 default:
00181 return "unable to load library";
00182 }
00183 }
00184
00185
00186 static void ll_unloadlib (void *lib) {
00187 NSUnLinkModule((NSModule)lib, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES);
00188 }
00189
00190
00191 static void *ll_load (lua_State *L, const char *path) {
00192 NSObjectFileImage img;
00193 NSObjectFileImageReturnCode ret;
00194
00195 if(!_dyld_present()) {
00196 lua_pushliteral(L, "dyld not present");
00197 return NULL;
00198 }
00199 ret = NSCreateObjectFileImageFromFile(path, &img);
00200 if (ret == NSObjectFileImageSuccess) {
00201 NSModule mod = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE |
00202 NSLINKMODULE_OPTION_RETURN_ON_ERROR);
00203 NSDestroyObjectFileImage(img);
00204 if (mod == NULL) pusherror(L);
00205 return mod;
00206 }
00207 lua_pushstring(L, errorfromcode(ret));
00208 return NULL;
00209 }
00210
00211
00212 static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
00213 NSSymbol nss = NSLookupSymbolInModule((NSModule)lib, sym);
00214 if (nss == NULL) {
00215 lua_pushfstring(L, "symbol " LUA_QS " not found", sym);
00216 return NULL;
00217 }
00218 return (lua_CFunction)NSAddressOfSymbol(nss);
00219 }
00220
00221
00222
00223
00224
00225 #else
00226
00227
00228
00229
00230
00231
00232 #undef LIB_FAIL
00233 #define LIB_FAIL "absent"
00234
00235
00236 #define DLMSG "dynamic libraries not enabled; check your Lua installation"
00237
00238
00239 static void ll_unloadlib (void *lib) {
00240 (void)lib;
00241 }
00242
00243
00244 static void *ll_load (lua_State *L, const char *path) {
00245 (void)path;
00246 lua_pushliteral(L, DLMSG);
00247 return NULL;
00248 }
00249
00250
00251 static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
00252 (void)lib; (void)sym;
00253 lua_pushliteral(L, DLMSG);
00254 return NULL;
00255 }
00256
00257
00258 #endif
00259
00260
00261
00262 static void **ll_register (lua_State *L, const char *path) {
00263 void **plib;
00264 lua_pushfstring(L, "%s%s", LIBPREFIX, path);
00265 lua_gettable(L, LUA_REGISTRYINDEX);
00266 if (!lua_isnil(L, -1))
00267 plib = (void **)lua_touserdata(L, -1);
00268 else {
00269 lua_pop(L, 1);
00270 plib = (void **)lua_newuserdata(L, sizeof(const void *));
00271 *plib = NULL;
00272 luaL_getmetatable(L, "_LOADLIB");
00273 lua_setmetatable(L, -2);
00274 lua_pushfstring(L, "%s%s", LIBPREFIX, path);
00275 lua_pushvalue(L, -2);
00276 lua_settable(L, LUA_REGISTRYINDEX);
00277 }
00278 return plib;
00279 }
00280
00281
00282
00283
00284
00285
00286 static int gctm (lua_State *L) {
00287 void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB");
00288 if (*lib) ll_unloadlib(*lib);
00289 *lib = NULL;
00290 return 0;
00291 }
00292
00293
00294 static int ll_loadfunc (lua_State *L, const char *path, const char *sym) {
00295 void **reg = ll_register(L, path);
00296 if (*reg == NULL) *reg = ll_load(L, path);
00297 if (*reg == NULL)
00298 return ERRLIB;
00299 else {
00300 lua_CFunction f = ll_sym(L, *reg, sym);
00301 if (f == NULL)
00302 return ERRFUNC;
00303 lua_pushcfunction(L, f);
00304 return 0;
00305 }
00306 }
00307
00308
00309 static int ll_loadlib (lua_State *L) {
00310 const char *path = luaL_checkstring(L, 1);
00311 const char *init = luaL_checkstring(L, 2);
00312 int stat = ll_loadfunc(L, path, init);
00313 if (stat == 0)
00314 return 1;
00315 else {
00316 lua_pushnil(L);
00317 lua_insert(L, -2);
00318 lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init");
00319 return 3;
00320 }
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 static int readable (const char *filename) {
00333 FILE *f = fopen(filename, "r");
00334 if (f == NULL) return 0;
00335 fclose(f);
00336 return 1;
00337 }
00338
00339
00340 static const char *pushnexttemplate (lua_State *L, const char *path) {
00341 const char *l;
00342 while (*path == *LUA_PATHSEP) path++;
00343 if (*path == '\0') return NULL;
00344 l = strchr(path, *LUA_PATHSEP);
00345 if (l == NULL) l = path + strlen(path);
00346 lua_pushlstring(L, path, l - path);
00347 return l;
00348 }
00349
00350
00351 static const char *findfile (lua_State *L, const char *name,
00352 const char *pname) {
00353 const char *path;
00354 name = luaL_gsub(L, name, ".", LUA_DIRSEP);
00355 lua_getfield(L, LUA_ENVIRONINDEX, pname);
00356 path = lua_tostring(L, -1);
00357 if (path == NULL)
00358 luaL_error(L, LUA_QL("package.%s") " must be a string", pname);
00359 lua_pushliteral(L, "");
00360 while ((path = pushnexttemplate(L, path)) != NULL) {
00361 const char *filename;
00362 filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name);
00363 lua_remove(L, -2);
00364 if (readable(filename))
00365 return filename;
00366 lua_pushfstring(L, "\n\tno file " LUA_QS, filename);
00367 lua_remove(L, -2);
00368 lua_concat(L, 2);
00369 }
00370 return NULL;
00371 }
00372
00373
00374 static void loaderror (lua_State *L, const char *filename) {
00375 luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s",
00376 lua_tostring(L, 1), filename, lua_tostring(L, -1));
00377 }
00378
00379
00380 static int loader_Lua (lua_State *L) {
00381 const char *filename;
00382 const char *name = luaL_checkstring(L, 1);
00383 filename = findfile(L, name, "path");
00384 if (filename == NULL) return 1;
00385 if (luaL_loadfile(L, filename) != 0)
00386 loaderror(L, filename);
00387 return 1;
00388 }
00389
00390
00391 static const char *mkfuncname (lua_State *L, const char *modname) {
00392 const char *funcname;
00393 const char *mark = strchr(modname, *LUA_IGMARK);
00394 if (mark) modname = mark + 1;
00395 funcname = luaL_gsub(L, modname, ".", LUA_OFSEP);
00396 funcname = lua_pushfstring(L, POF"%s", funcname);
00397 lua_remove(L, -2);
00398 return funcname;
00399 }
00400
00401
00402 static int loader_C (lua_State *L) {
00403 const char *funcname;
00404 const char *name = luaL_checkstring(L, 1);
00405 const char *filename = findfile(L, name, "cpath");
00406 if (filename == NULL) return 1;
00407 funcname = mkfuncname(L, name);
00408 if (ll_loadfunc(L, filename, funcname) != 0)
00409 loaderror(L, filename);
00410 return 1;
00411 }
00412
00413
00414 static int loader_Croot (lua_State *L) {
00415 const char *funcname;
00416 const char *filename;
00417 const char *name = luaL_checkstring(L, 1);
00418 const char *p = strchr(name, '.');
00419 int stat;
00420 if (p == NULL) return 0;
00421 lua_pushlstring(L, name, p - name);
00422 filename = findfile(L, lua_tostring(L, -1), "cpath");
00423 if (filename == NULL) return 1;
00424 funcname = mkfuncname(L, name);
00425 if ((stat = ll_loadfunc(L, filename, funcname)) != 0) {
00426 if (stat != ERRFUNC) loaderror(L, filename);
00427 lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS,
00428 name, filename);
00429 return 1;
00430 }
00431 return 1;
00432 }
00433
00434
00435 static int loader_preload (lua_State *L) {
00436 const char *name = luaL_checkstring(L, 1);
00437 lua_getfield(L, LUA_ENVIRONINDEX, "preload");
00438 if (!lua_istable(L, -1))
00439 luaL_error(L, LUA_QL("package.preload") " must be a table");
00440 lua_getfield(L, -1, name);
00441 if (lua_isnil(L, -1))
00442 lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
00443 return 1;
00444 }
00445
00446
00447 static const int sentinel_ = 0;
00448 #define sentinel ((void *)&sentinel_)
00449
00450
00451 static int ll_require (lua_State *L) {
00452 const char *name = luaL_checkstring(L, 1);
00453 int i;
00454 lua_settop(L, 1);
00455 lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
00456 lua_getfield(L, 2, name);
00457 if (lua_toboolean(L, -1)) {
00458 if (lua_touserdata(L, -1) == sentinel)
00459 luaL_error(L, "loop or previous error loading module " LUA_QS, name);
00460 return 1;
00461 }
00462
00463 lua_getfield(L, LUA_ENVIRONINDEX, "loaders");
00464 if (!lua_istable(L, -1))
00465 luaL_error(L, LUA_QL("package.loaders") " must be a table");
00466 lua_pushliteral(L, "");
00467 for (i=1; ; i++) {
00468 lua_rawgeti(L, -2, i);
00469 if (lua_isnil(L, -1))
00470 luaL_error(L, "module " LUA_QS " not found:%s",
00471 name, lua_tostring(L, -2));
00472 lua_pushstring(L, name);
00473 lua_call(L, 1, 1);
00474 if (lua_isfunction(L, -1))
00475 break;
00476 else if (lua_isstring(L, -1))
00477 lua_concat(L, 2);
00478 else
00479 lua_pop(L, 1);
00480 }
00481 lua_pushlightuserdata(L, sentinel);
00482 lua_setfield(L, 2, name);
00483 lua_pushstring(L, name);
00484 lua_call(L, 1, 1);
00485 if (!lua_isnil(L, -1))
00486 lua_setfield(L, 2, name);
00487 lua_getfield(L, 2, name);
00488 if (lua_touserdata(L, -1) == sentinel) {
00489 lua_pushboolean(L, 1);
00490 lua_pushvalue(L, -1);
00491 lua_setfield(L, 2, name);
00492 }
00493 return 1;
00494 }
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 static void setfenv (lua_State *L) {
00508 lua_Debug ar;
00509 lua_getstack(L, 1, &ar);
00510 lua_getinfo(L, "f", &ar);
00511 lua_pushvalue(L, -2);
00512 lua_setfenv(L, -2);
00513 lua_pop(L, 1);
00514 }
00515
00516
00517 static void dooptions (lua_State *L, int n) {
00518 int i;
00519 for (i = 2; i <= n; i++) {
00520 lua_pushvalue(L, i);
00521 lua_pushvalue(L, -2);
00522 lua_call(L, 1, 0);
00523 }
00524 }
00525
00526
00527 static void modinit (lua_State *L, const char *modname) {
00528 const char *dot;
00529 lua_pushvalue(L, -1);
00530 lua_setfield(L, -2, "_M");
00531 lua_pushstring(L, modname);
00532 lua_setfield(L, -2, "_NAME");
00533 dot = strrchr(modname, '.');
00534 if (dot == NULL) dot = modname;
00535 else dot++;
00536
00537 lua_pushlstring(L, modname, dot - modname);
00538 lua_setfield(L, -2, "_PACKAGE");
00539 }
00540
00541
00542 static int ll_module (lua_State *L) {
00543 const char *modname = luaL_checkstring(L, 1);
00544 int loaded = lua_gettop(L) + 1;
00545 lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
00546 lua_getfield(L, loaded, modname);
00547 if (!lua_istable(L, -1)) {
00548 lua_pop(L, 1);
00549
00550 if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL)
00551 return luaL_error(L, "name conflict for module " LUA_QS, modname);
00552 lua_pushvalue(L, -1);
00553 lua_setfield(L, loaded, modname);
00554 }
00555
00556 lua_getfield(L, -1, "_NAME");
00557 if (!lua_isnil(L, -1))
00558 lua_pop(L, 1);
00559 else {
00560 lua_pop(L, 1);
00561 modinit(L, modname);
00562 }
00563 lua_pushvalue(L, -1);
00564 setfenv(L);
00565 dooptions(L, loaded - 1);
00566 return 0;
00567 }
00568
00569
00570 static int ll_seeall (lua_State *L) {
00571 luaL_checktype(L, 1, LUA_TTABLE);
00572 if (!lua_getmetatable(L, 1)) {
00573 lua_createtable(L, 0, 1);
00574 lua_pushvalue(L, -1);
00575 lua_setmetatable(L, 1);
00576 }
00577 lua_pushvalue(L, LUA_GLOBALSINDEX);
00578 lua_setfield(L, -2, "__index");
00579 return 0;
00580 }
00581
00582
00583
00584
00585
00586
00587
00588 #define AUXMARK "\1"
00589
00590 static void setpath (lua_State *L, const char *fieldname, const char *envname,
00591 const char *def) {
00592 const char *path = getenv(envname);
00593 if (path == NULL)
00594 lua_pushstring(L, def);
00595 else {
00596
00597 path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP,
00598 LUA_PATHSEP AUXMARK LUA_PATHSEP);
00599 luaL_gsub(L, path, AUXMARK, def);
00600 lua_remove(L, -2);
00601 }
00602 setprogdir(L);
00603 lua_setfield(L, -2, fieldname);
00604 }
00605
00606
00607 static const luaL_Reg pk_funcs[] = {
00608 {"loadlib", ll_loadlib},
00609 {"seeall", ll_seeall},
00610 {NULL, NULL}
00611 };
00612
00613
00614 static const luaL_Reg ll_funcs[] = {
00615 {"module", ll_module},
00616 {"require", ll_require},
00617 {NULL, NULL}
00618 };
00619
00620
00621 static const lua_CFunction loaders[] =
00622 {loader_preload, loader_Lua, loader_C, loader_Croot, NULL};
00623
00624
00625 LUALIB_API int luaopen_package (lua_State *L) {
00626 int i;
00627
00628 luaL_newmetatable(L, "_LOADLIB");
00629 lua_pushcfunction(L, gctm);
00630 lua_setfield(L, -2, "__gc");
00631
00632 luaL_register(L, LUA_LOADLIBNAME, pk_funcs);
00633 #if defined(LUA_COMPAT_LOADLIB)
00634 lua_getfield(L, -1, "loadlib");
00635 lua_setfield(L, LUA_GLOBALSINDEX, "loadlib");
00636 #endif
00637 lua_pushvalue(L, -1);
00638 lua_replace(L, LUA_ENVIRONINDEX);
00639
00640 lua_createtable(L, 0, sizeof(loaders)/sizeof(loaders[0]) - 1);
00641
00642 for (i=0; loaders[i] != NULL; i++) {
00643 lua_pushcfunction(L, loaders[i]);
00644 lua_rawseti(L, -2, i+1);
00645 }
00646 lua_setfield(L, -2, "loaders");
00647 setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT);
00648 setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT);
00649
00650 lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n"
00651 LUA_EXECDIR "\n" LUA_IGMARK);
00652 lua_setfield(L, -2, "config");
00653
00654 luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2);
00655 lua_setfield(L, -2, "loaded");
00656
00657 lua_newtable(L);
00658 lua_setfield(L, -2, "preload");
00659 lua_pushvalue(L, LUA_GLOBALSINDEX);
00660 luaL_register(L, NULL, ll_funcs);
00661 lua_pop(L, 1);
00662 return 1;
00663 }
00664