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