1 /* $NetBSD: loadlib.c,v 1.2 2014/07/19 18:38:34 lneto Exp $ */ 2 3 /* 4 ** $Id: loadlib.c,v 1.2 2014/07/19 18:38:34 lneto Exp $ 5 ** Dynamic library loader for Lua 6 ** See Copyright Notice in lua.h 7 ** 8 ** This module contains an implementation of loadlib for Unix systems 9 ** that have dlfcn, an implementation for Windows, and a stub for other 10 ** systems. 11 */ 12 13 14 /* 15 ** if needed, includes windows header before everything else 16 */ 17 #if defined(_WIN32) 18 #include <windows.h> 19 #endif 20 21 22 #include <stdlib.h> 23 #include <string.h> 24 25 26 #define loadlib_c 27 #define LUA_LIB 28 29 #include "lua.h" 30 31 #include "lauxlib.h" 32 #include "lualib.h" 33 34 35 /* 36 ** LUA_PATH_VAR and LUA_CPATH_VAR are the names of the environment 37 ** variables that Lua check to set its paths. 38 */ 39 #if !defined(LUA_PATH_VAR) 40 #define LUA_PATH_VAR "LUA_PATH" 41 #endif 42 43 #if !defined(LUA_CPATH_VAR) 44 #define LUA_CPATH_VAR "LUA_CPATH" 45 #endif 46 47 #define LUA_PATHSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR 48 49 #define LUA_PATHVARVERSION LUA_PATH_VAR LUA_PATHSUFFIX 50 #define LUA_CPATHVARVERSION LUA_CPATH_VAR LUA_PATHSUFFIX 51 52 /* 53 ** LUA_PATH_SEP is the character that separates templates in a path. 54 ** LUA_PATH_MARK is the string that marks the substitution points in a 55 ** template. 56 ** LUA_EXEC_DIR in a Windows path is replaced by the executable's 57 ** directory. 58 ** LUA_IGMARK is a mark to ignore all before it when building the 59 ** luaopen_ function name. 60 */ 61 #if !defined (LUA_PATH_SEP) 62 #define LUA_PATH_SEP ";" 63 #endif 64 #if !defined (LUA_PATH_MARK) 65 #define LUA_PATH_MARK "?" 66 #endif 67 #if !defined (LUA_EXEC_DIR) 68 #define LUA_EXEC_DIR "!" 69 #endif 70 #if !defined (LUA_IGMARK) 71 #define LUA_IGMARK "-" 72 #endif 73 74 75 /* 76 ** LUA_CSUBSEP is the character that replaces dots in submodule names 77 ** when searching for a C loader. 78 ** LUA_LSUBSEP is the character that replaces dots in submodule names 79 ** when searching for a Lua loader. 80 */ 81 #if !defined(LUA_CSUBSEP) 82 #define LUA_CSUBSEP LUA_DIRSEP 83 #endif 84 85 #if !defined(LUA_LSUBSEP) 86 #define LUA_LSUBSEP LUA_DIRSEP 87 #endif 88 89 90 /* prefix for open functions in C libraries */ 91 #define LUA_POF "luaopen_" 92 93 /* separator for open functions in C libraries */ 94 #define LUA_OFSEP "_" 95 96 97 /* table (in the registry) that keeps handles for all loaded C libraries */ 98 #define CLIBS "_CLIBS" 99 100 #define LIB_FAIL "open" 101 102 103 /* error codes for ll_loadfunc */ 104 #define ERRLIB 1 105 #define ERRFUNC 2 106 107 #define setprogdir(L) ((void)0) 108 109 110 /* 111 ** system-dependent functions 112 */ 113 static void ll_unloadlib (void *lib); 114 static void *ll_load (lua_State *L, const char *path, int seeglb); 115 static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); 116 117 118 119 #if defined(LUA_USE_DLOPEN) 120 /* 121 ** {======================================================================== 122 ** This is an implementation of loadlib based on the dlfcn interface. 123 ** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, 124 ** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least 125 ** as an emulation layer on top of native functions. 126 ** ========================================================================= 127 */ 128 129 #include <dlfcn.h> 130 131 static void ll_unloadlib (void *lib) { 132 dlclose(lib); 133 } 134 135 136 static void *ll_load (lua_State *L, const char *path, int seeglb) { 137 void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL)); 138 if (lib == NULL) lua_pushstring(L, dlerror()); 139 return lib; 140 } 141 142 143 static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { 144 lua_CFunction f = (lua_CFunction)dlsym(lib, sym); 145 if (f == NULL) lua_pushstring(L, dlerror()); 146 return f; 147 } 148 149 /* }====================================================== */ 150 151 152 153 #elif defined(LUA_DL_DLL) 154 /* 155 ** {====================================================================== 156 ** This is an implementation of loadlib for Windows using native functions. 157 ** ======================================================================= 158 */ 159 160 #undef setprogdir 161 162 /* 163 ** optional flags for LoadLibraryEx 164 */ 165 #if !defined(LUA_LLE_FLAGS) 166 #define LUA_LLE_FLAGS 0 167 #endif 168 169 170 static void setprogdir (lua_State *L) { 171 char buff[MAX_PATH + 1]; 172 char *lb; 173 DWORD nsize = sizeof(buff)/sizeof(char); 174 DWORD n = GetModuleFileNameA(NULL, buff, nsize); 175 if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) 176 luaL_error(L, "unable to get ModuleFileName"); 177 else { 178 *lb = '\0'; 179 luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff); 180 lua_remove(L, -2); /* remove original string */ 181 } 182 } 183 184 185 static void pusherror (lua_State *L) { 186 int error = GetLastError(); 187 char buffer[128]; 188 if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, 189 NULL, error, 0, buffer, sizeof(buffer)/sizeof(char), NULL)) 190 lua_pushstring(L, buffer); 191 else 192 lua_pushfstring(L, "system error %d\n", error); 193 } 194 195 static void ll_unloadlib (void *lib) { 196 FreeLibrary((HMODULE)lib); 197 } 198 199 200 static void *ll_load (lua_State *L, const char *path, int seeglb) { 201 HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS); 202 (void)(seeglb); /* not used: symbols are 'global' by default */ 203 if (lib == NULL) pusherror(L); 204 return lib; 205 } 206 207 208 static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { 209 lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym); 210 if (f == NULL) pusherror(L); 211 return f; 212 } 213 214 /* }====================================================== */ 215 216 217 #else 218 /* 219 ** {====================================================== 220 ** Fallback for other systems 221 ** ======================================================= 222 */ 223 224 #undef LIB_FAIL 225 #define LIB_FAIL "absent" 226 227 228 #define DLMSG "dynamic libraries not enabled; check your Lua installation" 229 230 231 static void ll_unloadlib (void *lib) { 232 (void)(lib); /* not used */ 233 } 234 235 236 static void *ll_load (lua_State *L, const char *path, int seeglb) { 237 (void)(path); (void)(seeglb); /* not used */ 238 lua_pushliteral(L, DLMSG); 239 return NULL; 240 } 241 242 243 static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { 244 (void)(lib); (void)(sym); /* not used */ 245 lua_pushliteral(L, DLMSG); 246 return NULL; 247 } 248 249 /* }====================================================== */ 250 #endif 251 252 253 static void *ll_checkclib (lua_State *L, const char *path) { 254 void *plib; 255 lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); 256 lua_getfield(L, -1, path); 257 plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */ 258 lua_pop(L, 2); /* pop CLIBS table and 'plib' */ 259 return plib; 260 } 261 262 263 static void ll_addtoclib (lua_State *L, const char *path, void *plib) { 264 lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); 265 lua_pushlightuserdata(L, plib); 266 lua_pushvalue(L, -1); 267 lua_setfield(L, -3, path); /* CLIBS[path] = plib */ 268 lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */ 269 lua_pop(L, 1); /* pop CLIBS table */ 270 } 271 272 273 /* 274 ** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib 275 ** handles in list CLIBS 276 */ 277 static int gctm (lua_State *L) { 278 int n = luaL_len(L, 1); 279 for (; n >= 1; n--) { /* for each handle, in reverse order */ 280 lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */ 281 ll_unloadlib(lua_touserdata(L, -1)); 282 lua_pop(L, 1); /* pop handle */ 283 } 284 return 0; 285 } 286 287 288 static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { 289 void *reg = ll_checkclib(L, path); /* check loaded C libraries */ 290 if (reg == NULL) { /* must load library? */ 291 reg = ll_load(L, path, *sym == '*'); 292 if (reg == NULL) return ERRLIB; /* unable to load library */ 293 ll_addtoclib(L, path, reg); 294 } 295 if (*sym == '*') { /* loading only library (no function)? */ 296 lua_pushboolean(L, 1); /* return 'true' */ 297 return 0; /* no errors */ 298 } 299 else { 300 lua_CFunction f = ll_sym(L, reg, sym); 301 if (f == NULL) 302 return ERRFUNC; /* unable to find function */ 303 lua_pushcfunction(L, f); /* else create new function */ 304 return 0; /* no errors */ 305 } 306 } 307 308 309 static int ll_loadlib (lua_State *L) { 310 const char *path = luaL_checkstring(L, 1); 311 const char *init = luaL_checkstring(L, 2); 312 int stat = ll_loadfunc(L, path, init); 313 if (stat == 0) /* no errors? */ 314 return 1; /* return the loaded function */ 315 else { /* error; error message is on stack top */ 316 lua_pushnil(L); 317 lua_insert(L, -2); 318 lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); 319 return 3; /* return nil, error message, and where */ 320 } 321 } 322 323 324 325 /* 326 ** {====================================================== 327 ** 'require' function 328 ** ======================================================= 329 */ 330 331 332 static int readable (const char *filename) { 333 FILE *f = fopen(filename, "r"); /* try to open file */ 334 if (f == NULL) return 0; /* open failed */ 335 fclose(f); 336 return 1; 337 } 338 339 340 static const char *pushnexttemplate (lua_State *L, const char *path) { 341 const char *l; 342 while (*path == *LUA_PATH_SEP) path++; /* skip separators */ 343 if (*path == '\0') return NULL; /* no more templates */ 344 l = strchr(path, *LUA_PATH_SEP); /* find next separator */ 345 if (l == NULL) l = path + strlen(path); 346 lua_pushlstring(L, path, l - path); /* template */ 347 return l; 348 } 349 350 351 static const char *searchpath (lua_State *L, const char *name, 352 const char *path, 353 const char *sep, 354 const char *dirsep) { 355 luaL_Buffer msg; /* to build error message */ 356 luaL_buffinit(L, &msg); 357 if (*sep != '\0') /* non-empty separator? */ 358 name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */ 359 while ((path = pushnexttemplate(L, path)) != NULL) { 360 const char *filename = luaL_gsub(L, lua_tostring(L, -1), 361 LUA_PATH_MARK, name); 362 lua_remove(L, -2); /* remove path template */ 363 if (readable(filename)) /* does file exist and is readable? */ 364 return filename; /* return that file name */ 365 lua_pushfstring(L, "\n\tno file " LUA_QS, filename); 366 lua_remove(L, -2); /* remove file name */ 367 luaL_addvalue(&msg); /* concatenate error msg. entry */ 368 } 369 luaL_pushresult(&msg); /* create error message */ 370 return NULL; /* not found */ 371 } 372 373 374 static int ll_searchpath (lua_State *L) { 375 const char *f = searchpath(L, luaL_checkstring(L, 1), 376 luaL_checkstring(L, 2), 377 luaL_optstring(L, 3, "."), 378 luaL_optstring(L, 4, LUA_DIRSEP)); 379 if (f != NULL) return 1; 380 else { /* error message is on top of the stack */ 381 lua_pushnil(L); 382 lua_insert(L, -2); 383 return 2; /* return nil + error message */ 384 } 385 } 386 387 388 static const char *findfile (lua_State *L, const char *name, 389 const char *pname, 390 const char *dirsep) { 391 const char *path; 392 lua_getfield(L, lua_upvalueindex(1), pname); 393 path = lua_tostring(L, -1); 394 if (path == NULL) 395 luaL_error(L, LUA_QL("package.%s") " must be a string", pname); 396 return searchpath(L, name, path, ".", dirsep); 397 } 398 399 400 static int checkload (lua_State *L, int stat, const char *filename) { 401 if (stat) { /* module loaded successfully? */ 402 lua_pushstring(L, filename); /* will be 2nd argument to module */ 403 return 2; /* return open function and file name */ 404 } 405 else 406 return luaL_error(L, "error loading module " LUA_QS 407 " from file " LUA_QS ":\n\t%s", 408 lua_tostring(L, 1), filename, lua_tostring(L, -1)); 409 } 410 411 412 static int searcher_Lua (lua_State *L) { 413 const char *filename; 414 const char *name = luaL_checkstring(L, 1); 415 filename = findfile(L, name, "path", LUA_LSUBSEP); 416 if (filename == NULL) return 1; /* module not found in this path */ 417 return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename); 418 } 419 420 421 static int loadfunc (lua_State *L, const char *filename, const char *modname) { 422 const char *funcname; 423 const char *mark; 424 modname = luaL_gsub(L, modname, ".", LUA_OFSEP); 425 mark = strchr(modname, *LUA_IGMARK); 426 if (mark) { 427 int stat; 428 funcname = lua_pushlstring(L, modname, mark - modname); 429 funcname = lua_pushfstring(L, LUA_POF"%s", funcname); 430 stat = ll_loadfunc(L, filename, funcname); 431 if (stat != ERRFUNC) return stat; 432 modname = mark + 1; /* else go ahead and try old-style name */ 433 } 434 funcname = lua_pushfstring(L, LUA_POF"%s", modname); 435 return ll_loadfunc(L, filename, funcname); 436 } 437 438 439 static int searcher_C (lua_State *L) { 440 const char *name = luaL_checkstring(L, 1); 441 const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP); 442 if (filename == NULL) return 1; /* module not found in this path */ 443 return checkload(L, (loadfunc(L, filename, name) == 0), filename); 444 } 445 446 447 static int searcher_Croot (lua_State *L) { 448 const char *filename; 449 const char *name = luaL_checkstring(L, 1); 450 const char *p = strchr(name, '.'); 451 int stat; 452 if (p == NULL) return 0; /* is root */ 453 lua_pushlstring(L, name, p - name); 454 filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP); 455 if (filename == NULL) return 1; /* root not found */ 456 if ((stat = loadfunc(L, filename, name)) != 0) { 457 if (stat != ERRFUNC) 458 return checkload(L, 0, filename); /* real error */ 459 else { /* open function not found */ 460 lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS, 461 name, filename); 462 return 1; 463 } 464 } 465 lua_pushstring(L, filename); /* will be 2nd argument to module */ 466 return 2; 467 } 468 469 470 static int searcher_preload (lua_State *L) { 471 const char *name = luaL_checkstring(L, 1); 472 lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD"); 473 if (lua_getfield(L, -1, name) == LUA_TNIL) /* not found? */ 474 lua_pushfstring(L, "\n\tno field package.preload['%s']", name); 475 return 1; 476 } 477 478 479 static void findloader (lua_State *L, const char *name) { 480 int i; 481 luaL_Buffer msg; /* to build error message */ 482 luaL_buffinit(L, &msg); 483 lua_getfield(L, lua_upvalueindex(1), "searchers"); /* will be at index 3 */ 484 if (!lua_istable(L, 3)) 485 luaL_error(L, LUA_QL("package.searchers") " must be a table"); 486 /* iterate over available searchers to find a loader */ 487 for (i = 1; ; i++) { 488 if (lua_rawgeti(L, 3, i) == LUA_TNIL) { /* no more searchers? */ 489 lua_pop(L, 1); /* remove nil */ 490 luaL_pushresult(&msg); /* create error message */ 491 luaL_error(L, "module " LUA_QS " not found:%s", 492 name, lua_tostring(L, -1)); 493 } 494 lua_pushstring(L, name); 495 lua_call(L, 1, 2); /* call it */ 496 if (lua_isfunction(L, -2)) /* did it find a loader? */ 497 return; /* module loader found */ 498 else if (lua_isstring(L, -2)) { /* searcher returned error message? */ 499 lua_pop(L, 1); /* remove extra return */ 500 luaL_addvalue(&msg); /* concatenate error message */ 501 } 502 else 503 lua_pop(L, 2); /* remove both returns */ 504 } 505 } 506 507 508 static int ll_require (lua_State *L) { 509 const char *name = luaL_checkstring(L, 1); 510 lua_settop(L, 1); /* _LOADED table will be at index 2 */ 511 lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); 512 lua_getfield(L, 2, name); /* _LOADED[name] */ 513 if (lua_toboolean(L, -1)) /* is it there? */ 514 return 1; /* package is already loaded */ 515 /* else must load package */ 516 lua_pop(L, 1); /* remove 'getfield' result */ 517 findloader(L, name); 518 lua_pushstring(L, name); /* pass name as argument to module loader */ 519 lua_insert(L, -2); /* name is 1st argument (before search data) */ 520 lua_call(L, 2, 1); /* run loader to load module */ 521 if (!lua_isnil(L, -1)) /* non-nil return? */ 522 lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ 523 if (lua_getfield(L, 2, name) == LUA_TNIL) { /* module set no value? */ 524 lua_pushboolean(L, 1); /* use true as result */ 525 lua_pushvalue(L, -1); /* extra copy to be returned */ 526 lua_setfield(L, 2, name); /* _LOADED[name] = true */ 527 } 528 return 1; 529 } 530 531 /* }====================================================== */ 532 533 534 535 /* 536 ** {====================================================== 537 ** 'module' function 538 ** ======================================================= 539 */ 540 #if defined(LUA_COMPAT_MODULE) 541 542 /* 543 ** changes the environment variable of calling function 544 */ 545 static void set_env (lua_State *L) { 546 lua_Debug ar; 547 if (lua_getstack(L, 1, &ar) == 0 || 548 lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ 549 lua_iscfunction(L, -1)) 550 luaL_error(L, LUA_QL("module") " not called from a Lua function"); 551 lua_pushvalue(L, -2); /* copy new environment table to top */ 552 lua_setupvalue(L, -2, 1); 553 lua_pop(L, 1); /* remove function */ 554 } 555 556 557 static void dooptions (lua_State *L, int n) { 558 int i; 559 for (i = 2; i <= n; i++) { 560 if (lua_isfunction(L, i)) { /* avoid 'calling' extra info. */ 561 lua_pushvalue(L, i); /* get option (a function) */ 562 lua_pushvalue(L, -2); /* module */ 563 lua_call(L, 1, 0); 564 } 565 } 566 } 567 568 569 static void modinit (lua_State *L, const char *modname) { 570 const char *dot; 571 lua_pushvalue(L, -1); 572 lua_setfield(L, -2, "_M"); /* module._M = module */ 573 lua_pushstring(L, modname); 574 lua_setfield(L, -2, "_NAME"); 575 dot = strrchr(modname, '.'); /* look for last dot in module name */ 576 if (dot == NULL) dot = modname; 577 else dot++; 578 /* set _PACKAGE as package name (full module name minus last part) */ 579 lua_pushlstring(L, modname, dot - modname); 580 lua_setfield(L, -2, "_PACKAGE"); 581 } 582 583 584 static int ll_module (lua_State *L) { 585 const char *modname = luaL_checkstring(L, 1); 586 int lastarg = lua_gettop(L); /* last parameter */ 587 luaL_pushmodule(L, modname, 1); /* get/create module table */ 588 /* check whether table already has a _NAME field */ 589 if (lua_getfield(L, -1, "_NAME") != LUA_TNIL) 590 lua_pop(L, 1); /* table is an initialized module */ 591 else { /* no; initialize it */ 592 lua_pop(L, 1); 593 modinit(L, modname); 594 } 595 lua_pushvalue(L, -1); 596 set_env(L); 597 dooptions(L, lastarg); 598 return 1; 599 } 600 601 602 static int ll_seeall (lua_State *L) { 603 luaL_checktype(L, 1, LUA_TTABLE); 604 if (!lua_getmetatable(L, 1)) { 605 lua_createtable(L, 0, 1); /* create new metatable */ 606 lua_pushvalue(L, -1); 607 lua_setmetatable(L, 1); 608 } 609 lua_pushglobaltable(L); 610 lua_setfield(L, -2, "__index"); /* mt.__index = _G */ 611 return 0; 612 } 613 614 #endif 615 /* }====================================================== */ 616 617 618 619 /* auxiliary mark (for internal use) */ 620 #define AUXMARK "\1" 621 622 623 /* 624 ** return registry.LUA_NOENV as a boolean 625 */ 626 static int noenv (lua_State *L) { 627 int b; 628 lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); 629 b = lua_toboolean(L, -1); 630 lua_pop(L, 1); /* remove value */ 631 return b; 632 } 633 634 635 static void setpath (lua_State *L, const char *fieldname, const char *envname1, 636 const char *envname2, const char *def) { 637 const char *path = getenv(envname1); 638 if (path == NULL) /* no environment variable? */ 639 path = getenv(envname2); /* try alternative name */ 640 if (path == NULL || noenv(L)) /* no environment variable? */ 641 lua_pushstring(L, def); /* use default */ 642 else { 643 /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ 644 path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP, 645 LUA_PATH_SEP AUXMARK LUA_PATH_SEP); 646 luaL_gsub(L, path, AUXMARK, def); 647 lua_remove(L, -2); 648 } 649 setprogdir(L); 650 lua_setfield(L, -2, fieldname); 651 } 652 653 654 static const luaL_Reg pk_funcs[] = { 655 {"loadlib", ll_loadlib}, 656 {"searchpath", ll_searchpath}, 657 #if defined(LUA_COMPAT_MODULE) 658 {"seeall", ll_seeall}, 659 #endif 660 {NULL, NULL} 661 }; 662 663 664 static const luaL_Reg ll_funcs[] = { 665 #if defined(LUA_COMPAT_MODULE) 666 {"module", ll_module}, 667 #endif 668 {"require", ll_require}, 669 {NULL, NULL} 670 }; 671 672 673 static void createsearcherstable (lua_State *L) { 674 static const lua_CFunction searchers[] = 675 {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL}; 676 int i; 677 /* create 'searchers' table */ 678 lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0); 679 /* fill it with pre-defined searchers */ 680 for (i=0; searchers[i] != NULL; i++) { 681 lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */ 682 lua_pushcclosure(L, searchers[i], 1); 683 lua_rawseti(L, -2, i+1); 684 } 685 } 686 687 688 LUAMOD_API int luaopen_package (lua_State *L) { 689 /* create table CLIBS to keep track of loaded C libraries */ 690 luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); 691 lua_createtable(L, 0, 1); /* metatable for CLIBS */ 692 lua_pushcfunction(L, gctm); 693 lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */ 694 lua_setmetatable(L, -2); 695 /* create `package' table */ 696 luaL_newlib(L, pk_funcs); 697 createsearcherstable(L); 698 #if defined(LUA_COMPAT_LOADERS) 699 lua_pushvalue(L, -1); /* make a copy of 'searchers' table */ 700 lua_setfield(L, -3, "loaders"); /* put it in field `loaders' */ 701 #endif 702 lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ 703 /* set field 'path' */ 704 setpath(L, "path", LUA_PATHVARVERSION, LUA_PATH_VAR, LUA_PATH_DEFAULT); 705 /* set field 'cpath' */ 706 setpath(L, "cpath", LUA_CPATHVARVERSION, LUA_CPATH_VAR, LUA_CPATH_DEFAULT); 707 /* store config information */ 708 lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n" 709 LUA_EXEC_DIR "\n" LUA_IGMARK "\n"); 710 lua_setfield(L, -2, "config"); 711 /* set field `loaded' */ 712 luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); 713 lua_setfield(L, -2, "loaded"); 714 /* set field `preload' */ 715 luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD"); 716 lua_setfield(L, -2, "preload"); 717 lua_pushglobaltable(L); 718 lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */ 719 luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */ 720 lua_pop(L, 1); /* pop global table */ 721 return 1; /* return 'package' table */ 722 } 723 724