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 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 if (lua_getstack(L, 1, &ar) == 0 ||
00510 lua_getinfo(L, "f", &ar) == 0 ||
00511 lua_iscfunction(L, -1))
00512 luaL_error(L, LUA_QL("module") " not called from a Lua function");
00513 lua_pushvalue(L, -2);
00514 lua_setfenv(L, -2);
00515 lua_pop(L, 1);
00516 }
00517
00518
00519 static void dooptions (lua_State *L, int n) {
00520 int i;
00521 for (i = 2; i <= n; i++) {
00522 lua_pushvalue(L, i);
00523 lua_pushvalue(L, -2);
00524 lua_call(L, 1, 0);
00525 }
00526 }
00527
00528
00529 static void modinit (lua_State *L, const char *modname) {
00530 const char *dot;
00531 lua_pushvalue(L, -1);
00532 lua_setfield(L, -2, "_M");
00533 lua_pushstring(L, modname);
00534 lua_setfield(L, -2, "_NAME");
00535 dot = strrchr(modname, '.');
00536 if (dot == NULL) dot = modname;
00537 else dot++;
00538
00539 lua_pushlstring(L, modname, dot - modname);
00540 lua_setfield(L, -2, "_PACKAGE");
00541 }
00542
00543
00544 static int ll_module (lua_State *L) {
00545 const char *modname = luaL_checkstring(L, 1);
00546 int loaded = lua_gettop(L) + 1;
00547 lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
00548 lua_getfield(L, loaded, modname);
00549 if (!lua_istable(L, -1)) {
00550 lua_pop(L, 1);
00551
00552 if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL)
00553 return luaL_error(L, "name conflict for module " LUA_QS, modname);
00554 lua_pushvalue(L, -1);
00555 lua_setfield(L, loaded, modname);
00556 }
00557
00558 lua_getfield(L, -1, "_NAME");
00559 if (!lua_isnil(L, -1))
00560 lua_pop(L, 1);
00561 else {
00562 lua_pop(L, 1);
00563 modinit(L, modname);
00564 }
00565 lua_pushvalue(L, -1);
00566 setfenv(L);
00567 dooptions(L, loaded - 1);
00568 return 0;
00569 }
00570
00571
00572 static int ll_seeall (lua_State *L) {
00573 luaL_checktype(L, 1, LUA_TTABLE);
00574 if (!lua_getmetatable(L, 1)) {
00575 lua_createtable(L, 0, 1);
00576 lua_pushvalue(L, -1);
00577 lua_setmetatable(L, 1);
00578 }
00579 lua_pushvalue(L, LUA_GLOBALSINDEX);
00580 lua_setfield(L, -2, "__index");
00581 return 0;
00582 }
00583
00584
00585
00586
00587
00588
00589
00590 #define AUXMARK "\1"
00591
00592 static void setpath (lua_State *L, const char *fieldname, const char *envname,
00593 const char *def) {
00594 const char *path = getenv(envname);
00595 if (path == NULL)
00596 lua_pushstring(L, def);
00597 else {
00598
00599 path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP,
00600 LUA_PATHSEP AUXMARK LUA_PATHSEP);
00601 luaL_gsub(L, path, AUXMARK, def);
00602 lua_remove(L, -2);
00603 }
00604 setprogdir(L);
00605 lua_setfield(L, -2, fieldname);
00606 }
00607
00608
00609 static const luaL_Reg pk_funcs[] = {
00610 {"loadlib", ll_loadlib},
00611 {"seeall", ll_seeall},
00612 {NULL, NULL}
00613 };
00614
00615
00616 static const luaL_Reg ll_funcs[] = {
00617 {"module", ll_module},
00618 {"require", ll_require},
00619 {NULL, NULL}
00620 };
00621
00622
00623 static const lua_CFunction loaders[] =
00624 {loader_preload, loader_Lua, loader_C, loader_Croot, NULL};
00625
00626
00627 LUALIB_API int luaopen_package (lua_State *L) {
00628 int i;
00629
00630 luaL_newmetatable(L, "_LOADLIB");
00631 lua_pushcfunction(L, gctm);
00632 lua_setfield(L, -2, "__gc");
00633
00634 luaL_register(L, LUA_LOADLIBNAME, pk_funcs);
00635 #if defined(LUA_COMPAT_LOADLIB)
00636 lua_getfield(L, -1, "loadlib");
00637 lua_setfield(L, LUA_GLOBALSINDEX, "loadlib");
00638 #endif
00639 lua_pushvalue(L, -1);
00640 lua_replace(L, LUA_ENVIRONINDEX);
00641
00642 lua_createtable(L, sizeof(loaders)/sizeof(loaders[0]) - 1, 0);
00643
00644 for (i=0; loaders[i] != NULL; i++) {
00645 lua_pushcfunction(L, loaders[i]);
00646 lua_rawseti(L, -2, i+1);
00647 }
00648 lua_setfield(L, -2, "loaders");
00649 setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT);
00650 setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT);
00651
00652 lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n"
00653 LUA_EXECDIR "\n" LUA_IGMARK);
00654 lua_setfield(L, -2, "config");
00655
00656 luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2);
00657 lua_setfield(L, -2, "loaded");
00658
00659 lua_newtable(L);
00660 lua_setfield(L, -2, "preload");
00661 lua_pushvalue(L, LUA_GLOBALSINDEX);
00662 luaL_register(L, NULL, ll_funcs);
00663 lua_pop(L, 1);
00664 return 1;
00665 }