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