@ -1,14 +1,22 @@
/*
* * $ Id : loadlib . c , v 1. 52.1 .3 2008 / 08 / 06 13 : 29 : 28 roberto Exp $
* * $ Id : loadlib . c , v 1. 108 2011 / 12 / 12 16 : 34 : 03 roberto Exp $
* * Dynamic library loader for Lua
* * See Copyright Notice in lua . h
* *
* * This module contains an implementation of loadlib for Unix systems
* * that have dlfcn , an implementation for Darwin ( Mac OS X ) , an
* * implementation for Windows , and a stub for other systems.
* * that have dlfcn , an implementation for Windows , and a stub for other
* * systems.
*/
/*
* * if needed , includes windows header before everything else
*/
# if defined(_WIN32)
# include <windows.h>
# endif
# include <stdlib.h>
# include <string.h>
@ -22,6 +30,61 @@
# include "lualib.h"
/*
* * LUA_PATH and LUA_CPATH are the names of the environment
* * variables that Lua check to set its paths .
*/
# if !defined(LUA_PATH)
# define LUA_PATH "LUA_PATH"
# endif
# if !defined(LUA_CPATH)
# define LUA_CPATH "LUA_CPATH"
# endif
# define LUA_PATHSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
# define LUA_PATHVERSION LUA_PATH LUA_PATHSUFFIX
# define LUA_CPATHVERSION LUA_CPATH LUA_PATHSUFFIX
/*
* * LUA_PATH_SEP is the character that separates templates in a path .
* * LUA_PATH_MARK is the string that marks the substitution points in a
* * template .
* * LUA_EXEC_DIR in a Windows path is replaced by the executable ' s
* * directory .
* * LUA_IGMARK is a mark to ignore all before it when building the
* * luaopen_ function name .
*/
# if !defined (LUA_PATH_SEP)
# define LUA_PATH_SEP ";"
# endif
# if !defined (LUA_PATH_MARK)
# define LUA_PATH_MARK "?"
# endif
# if !defined (LUA_EXEC_DIR)
# define LUA_EXEC_DIR "!"
# endif
# if !defined (LUA_IGMARK)
# define LUA_IGMARK "-"
# endif
/*
* * LUA_CSUBSEP is the character that replaces dots in submodule names
* * when searching for a C loader .
* * LUA_LSUBSEP is the character that replaces dots in submodule names
* * when searching for a Lua loader .
*/
# if !defined(LUA_CSUBSEP)
# define LUA_CSUBSEP LUA_DIRSEP
# endif
# if !defined(LUA_LSUBSEP)
# define LUA_LSUBSEP LUA_DIRSEP
# endif
/* prefix for open functions in C libraries */
# define LUA_POF "luaopen_"
@ -42,13 +105,16 @@
# define setprogdir(L) ((void)0)
/*
* * system - dependent functions
*/
static void ll_unloadlib ( void * lib ) ;
static void * ll_load ( lua_State * L , const char * path ) ;
static void * ll_load ( lua_State * L , const char * path , int seeglb );
static lua_CFunction ll_sym ( lua_State * L , void * lib , const char * sym ) ;
# if defined(LUA_ DL _DLOPEN)
# if defined(LUA_ USE _DLOPEN)
/*
* * { = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
* * This is an implementation of loadlib based on the dlfcn interface .
@ -65,8 +131,8 @@ static void ll_unloadlib (void *lib) {
}
static void * ll_load ( lua_State * L , const char * path ) {
void * lib = dlopen ( path , RTLD_NOW ) ;
static void * ll_load ( lua_State * L , const char * path , int seeglb ) {
void * lib = dlopen ( path , RTLD_NOW | ( seeglb ? RTLD_GLOBAL : RTLD_LOCAL ) ) ;
if ( lib = = NULL ) lua_pushstring ( L , dlerror ( ) ) ;
return lib ;
}
@ -89,10 +155,15 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
* * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# include <windows.h>
# undef setprogdir
/*
* * optional flags for LoadLibraryEx
*/
# if !defined(LUA_LLE_FLAGS)
# define LUA_LLE_FLAGS 0
# endif
# undef setprogdir
static void setprogdir ( lua_State * L ) {
char buff [ MAX_PATH + 1 ] ;
@ -103,7 +174,7 @@ static void setprogdir (lua_State *L) {
luaL_error ( L , " unable to get ModuleFileName " ) ;
else {
* lb = ' \0 ' ;
luaL_gsub ( L , lua_tostring ( L , - 1 ) , LUA_EXEC DIR, buff ) ;
luaL_gsub ( L , lua_tostring ( L , - 1 ) , LUA_EXEC _ DIR, buff ) ;
lua_remove ( L , - 2 ) ; /* remove original string */
}
}
@ -113,26 +184,27 @@ static void pusherror (lua_State *L) {
int error = GetLastError ( ) ;
char buffer [ 128 ] ;
if ( FormatMessageA ( FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM ,
NULL , error , 0 , buffer , sizeof ( buffer ) , NULL ) )
NULL , error , 0 , buffer , sizeof ( buffer ) / sizeof ( char ) , NULL ) )
lua_pushstring ( L , buffer ) ;
else
lua_pushfstring ( L , " system error %d \n " , error ) ;
}
static void ll_unloadlib ( void * lib ) {
FreeLibrary ( ( H INSTANC E) lib ) ;
FreeLibrary ( ( H MODUL E) lib ) ;
}
static void * ll_load ( lua_State * L , const char * path ) {
HINSTANCE lib = LoadLibraryA ( path ) ;
static void * ll_load ( lua_State * L , const char * path , int seeglb ) {
HMODULE lib = LoadLibraryExA ( path , NULL , LUA_LLE_FLAGS ) ;
( void ) ( seeglb ) ; /* not used: symbols are 'global' by default */
if ( lib = = NULL ) pusherror ( L ) ;
return lib ;
}
static lua_CFunction ll_sym ( lua_State * L , void * lib , const char * sym ) {
lua_CFunction f = ( lua_CFunction ) GetProcAddress ( ( H INSTANC E) lib , sym ) ;
lua_CFunction f = ( lua_CFunction ) GetProcAddress ( ( H MODUL E) lib , sym ) ;
if ( f = = NULL ) pusherror ( L ) ;
return f ;
}
@ -140,88 +212,6 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
/* }====================================================== */
# elif defined(LUA_DL_DYLD)
/*
* * { = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
* * Native Mac OS X / Darwin Implementation
* * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# include <mach-o/dyld.h>
/* Mac appends a `_' before C function names */
# undef POF
# define POF "_" LUA_POF
static void pusherror ( lua_State * L ) {
const char * err_str ;
const char * err_file ;
NSLinkEditErrors err ;
int err_num ;
NSLinkEditError ( & err , & err_num , & err_file , & err_str ) ;
lua_pushstring ( L , err_str ) ;
}
static const char * errorfromcode ( NSObjectFileImageReturnCode ret ) {
switch ( ret ) {
case NSObjectFileImageInappropriateFile :
return " file is not a bundle " ;
case NSObjectFileImageArch :
return " library is for wrong CPU type " ;
case NSObjectFileImageFormat :
return " bad format " ;
case NSObjectFileImageAccess :
return " cannot access file " ;
case NSObjectFileImageFailure :
default :
return " unable to load library " ;
}
}
static void ll_unloadlib ( void * lib ) {
NSUnLinkModule ( ( NSModule ) lib , NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES ) ;
}
static void * ll_load ( lua_State * L , const char * path ) {
NSObjectFileImage img ;
NSObjectFileImageReturnCode ret ;
/* this would be a rare case, but prevents crashing if it happens */
if ( ! _dyld_present ( ) ) {
lua_pushliteral ( L , " dyld not present " ) ;
return NULL ;
}
ret = NSCreateObjectFileImageFromFile ( path , & img ) ;
if ( ret = = NSObjectFileImageSuccess ) {
NSModule mod = NSLinkModule ( img , path , NSLINKMODULE_OPTION_PRIVATE |
NSLINKMODULE_OPTION_RETURN_ON_ERROR ) ;
NSDestroyObjectFileImage ( img ) ;
if ( mod = = NULL ) pusherror ( L ) ;
return mod ;
}
lua_pushstring ( L , errorfromcode ( ret ) ) ;
return NULL ;
}
static lua_CFunction ll_sym ( lua_State * L , void * lib , const char * sym ) {
NSSymbol nss = NSLookupSymbolInModule ( ( NSModule ) lib , sym ) ;
if ( nss = = NULL ) {
lua_pushfstring ( L , " symbol " LUA_QS " not found " , sym ) ;
return NULL ;
}
return ( lua_CFunction ) NSAddressOfSymbol ( nss ) ;
}
/* }====================================================== */
# else
/*
* * { = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
@ -237,19 +227,19 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
static void ll_unloadlib ( void * lib ) {
( void ) lib ; /* to avoid warnings */
( void ) ( lib ) ; /* not used */
}
static void * ll_load ( lua_State * L , const char * path ) {
( void ) path ; /* to avoid warnings */
static void * ll_load ( lua_State * L , const char * path , int seeglb ) {
( void ) ( path ) ; ( void ) ( seeglb ) ; /* not used */
lua_pushliteral ( L , DLMSG ) ;
return NULL ;
}
static lua_CFunction ll_sym ( lua_State * L , void * lib , const char * sym ) {
( void ) lib ; ( void ) sym ; /* to avoid warnings */
( void ) ( lib ) ; ( void ) ( sym ) ; /* not used */
lua_pushliteral ( L , DLMSG ) ;
return NULL ;
}
@ -266,11 +256,10 @@ static void **ll_register (lua_State *L, const char *path) {
if ( ! lua_isnil ( L , - 1 ) ) /* is there an entry? */
plib = ( void * * ) lua_touserdata ( L , - 1 ) ;
else { /* no entry yet; create one */
lua_pop ( L , 1 ) ;
lua_pop ( L , 1 ) ; /* remove result from gettable */
plib = ( void * * ) lua_newuserdata ( L , sizeof ( const void * ) ) ;
* plib = NULL ;
luaL_getmetatable ( L , " _LOADLIB " ) ;
lua_setmetatable ( L , - 2 ) ;
luaL_setmetatable ( L , " _LOADLIB " ) ;
lua_pushfstring ( L , " %s%s " , LIBPREFIX , path ) ;
lua_pushvalue ( L , - 2 ) ;
lua_settable ( L , LUA_REGISTRYINDEX ) ;
@ -293,15 +282,18 @@ static int gctm (lua_State *L) {
static int ll_loadfunc ( lua_State * L , const char * path , const char * sym ) {
void * * reg = ll_register ( L , path ) ;
if ( * reg = = NULL ) * reg = ll_load ( L , path ) ;
if ( * reg = = NULL )
return ERRLIB ; /* unable to load library */
if ( * reg = = NULL ) * reg = ll_load ( L , path , * sym = = ' * ' ) ;
if ( * reg = = NULL ) return ERRLIB ; /* unable to load library */
if ( * sym = = ' * ' ) { /* loading only library (no function)? */
lua_pushboolean ( L , 1 ) ; /* return 'true' */
return 0 ; /* no errors */
}
else {
lua_CFunction f = ll_sym ( L , * reg , sym ) ;
if ( f = = NULL )
return ERRFUNC ; /* unable to find function */
lua_pushcfunction ( L , f ) ;
return 0 ; /* return function */
lua_pushcfunction ( L , f ) ; /* else create new function */
return 0 ; /* no errors */
}
}
@ -339,104 +331,137 @@ static int readable (const char *filename) {
static const char * pushnexttemplate ( lua_State * L , const char * path ) {
const char * l ;
while ( * path = = * LUA_PATH SEP) path + + ; /* skip separators */
while ( * path = = * LUA_PATH _ SEP) path + + ; /* skip separators */
if ( * path = = ' \0 ' ) return NULL ; /* no more templates */
l = strchr ( path , * LUA_PATH SEP) ; /* find next separator */
l = strchr ( path , * LUA_PATH _ SEP) ; /* find next separator */
if ( l = = NULL ) l = path + strlen ( path ) ;
lua_pushlstring ( L , path , l - path ) ; /* template */
return l ;
}
static const char * findfile ( lua_State * L , const char * name ,
const char * pname ) {
const char * path ;
name = luaL_gsub ( L , name , " . " , LUA_DIRSEP ) ;
lua_getfield ( L , LUA_ENVIRONINDEX , pname ) ;
path = lua_tostring ( L , - 1 ) ;
if ( path = = NULL )
luaL_error ( L , LUA_QL ( " package.%s " ) " must be a string " , pname ) ;
lua_pushliteral ( L , " " ) ; /* error accumulator */
static const char * searchpath ( lua_State * L , const char * name ,
const char * path ,
const char * sep ,
const char * dirsep ) {
luaL_Buffer msg ; /* to build error message */
luaL_buffinit ( L , & msg ) ;
if ( * sep ! = ' \0 ' ) /* non-empty separator? */
name = luaL_gsub ( L , name , sep , dirsep ) ; /* replace it by 'dirsep' */
while ( ( path = pushnexttemplate ( L , path ) ) ! = NULL ) {
const char * filename ;
filename = luaL_gsub ( L , lua_tostring ( L , - 1 ) , LUA_PATH_MARK , name ) ;
const char * filename = luaL_gsub ( L , lua_tostring ( L , - 1 ) ,
LUA_PATH_MARK , name ) ;
lua_remove ( L , - 2 ) ; /* remove path template */
if ( readable ( filename ) ) /* does file exist and is readable? */
return filename ; /* return that file name */
lua_pushfstring ( L , " \n \t no file " LUA_QS , filename ) ;
lua_remove ( L , - 2 ) ; /* remove file name */
lua _concat( L , 2 ) ; /* add entry to possible error message */
lua L_addvalue( & msg ) ; /* concatenate error msg. entry */
}
luaL_pushresult ( & msg ) ; /* create error message */
return NULL ; /* not found */
}
static void loaderror ( lua_State * L , const char * filename ) {
luaL_error ( L , " error loading module " LUA_QS " from file " LUA_QS " : \n \t %s " ,
lua_tostring ( L , 1 ) , filename , lua_tostring ( L , - 1 ) ) ;
static int ll_searchpath ( lua_State * L ) {
const char * f = searchpath ( L , luaL_checkstring ( L , 1 ) ,
luaL_checkstring ( L , 2 ) ,
luaL_optstring ( L , 3 , " . " ) ,
luaL_optstring ( L , 4 , LUA_DIRSEP ) ) ;
if ( f ! = NULL ) return 1 ;
else { /* error message is on top of the stack */
lua_pushnil ( L ) ;
lua_insert ( L , - 2 ) ;
return 2 ; /* return nil + error message */
}
}
static int loader_Lua ( lua_State * L ) {
static const char * findfile ( lua_State * L , const char * name ,
const char * pname ,
const char * dirsep ) {
const char * path ;
lua_getfield ( L , lua_upvalueindex ( 1 ) , pname ) ;
path = lua_tostring ( L , - 1 ) ;
if ( path = = NULL )
luaL_error ( L , LUA_QL ( " package.%s " ) " must be a string " , pname ) ;
return searchpath ( L , name , path , " . " , dirsep ) ;
}
static int checkload ( lua_State * L , int stat , const char * filename ) {
if ( stat ) { /* module loaded successfully? */
lua_pushstring ( L , filename ) ; /* will be 2nd argument to module */
return 2 ; /* return open function and file name */
}
else
return luaL_error ( L , " error loading module " LUA_QS
" from file " LUA_QS " : \n \t %s " ,
lua_tostring ( L , 1 ) , filename , lua_tostring ( L , - 1 ) ) ;
}
static int searcher_Lua ( lua_State * L ) {
const char * filename ;
const char * name = luaL_checkstring ( L , 1 ) ;
filename = findfile ( L , name , " path " ) ;
if ( filename = = NULL ) return 1 ; /* library not found in this path */
if ( luaL_loadfile ( L , filename ) ! = 0 )
loaderror ( L , filename ) ;
return 1 ; /* library loaded successfully */
filename = findfile ( L , name , " path " , LUA_LSUBSEP ) ;
if ( filename = = NULL ) return 1 ; /* module not found in this path */
return checkload ( L , ( luaL_loadfile ( L , filename ) = = LUA_OK ) , filename ) ;
}
static const char * mkfuncname ( lua_State * L , const char * modname ) {
static int loadfunc ( lua_State * L , const char * filename , const char * modname ) {
const char * funcname ;
const char * mark = strchr ( modname , * LUA_IGMARK ) ;
if ( mark ) modname = mark + 1 ;
funcname = luaL_gsub ( L , modname , " . " , LUA_OFSEP ) ;
funcname = lua_pushfstring ( L , POF " %s " , funcname ) ;
lua_remove ( L , - 2 ) ; /* remove 'gsub' result */
return funcname ;
const char * mark ;
modname = luaL_gsub ( L , modname , " . " , LUA_OFSEP ) ;
mark = strchr ( modname , * LUA_IGMARK ) ;
if ( mark ) {
int stat ;
funcname = lua_pushlstring ( L , modname , mark - modname ) ;
funcname = lua_pushfstring ( L , POF " %s " , funcname ) ;
stat = ll_loadfunc ( L , filename , funcname ) ;
if ( stat ! = ERRFUNC ) return stat ;
modname = mark + 1 ; /* else go ahead and try old-style name */
}
funcname = lua_pushfstring ( L , POF " %s " , modname ) ;
return ll_loadfunc ( L , filename , funcname ) ;
}
static int loader_C ( lua_State * L ) {
const char * funcname ;
static int searcher_C ( lua_State * L ) {
const char * name = luaL_checkstring ( L , 1 ) ;
const char * filename = findfile ( L , name , " cpath " ) ;
if ( filename = = NULL ) return 1 ; /* library not found in this path */
funcname = mkfuncname ( L , name ) ;
if ( ll_loadfunc ( L , filename , funcname ) ! = 0 )
loaderror ( L , filename ) ;
return 1 ; /* library loaded successfully */
const char * filename = findfile ( L , name , " cpath " , LUA_CSUBSEP ) ;
if ( filename = = NULL ) return 1 ; /* module not found in this path */
return checkload ( L , ( loadfunc ( L , filename , name ) = = 0 ) , filename ) ;
}
static int loader_Croot ( lua_State * L ) {
const char * funcname ;
static int searcher_Croot ( lua_State * L ) {
const char * filename ;
const char * name = luaL_checkstring ( L , 1 ) ;
const char * p = strchr ( name , ' . ' ) ;
int stat ;
if ( p = = NULL ) return 0 ; /* is root */
lua_pushlstring ( L , name , p - name ) ;
filename = findfile ( L , lua_tostring ( L , - 1 ) , " cpath " );
filename = findfile ( L , lua_tostring ( L , - 1 ) , " cpath " , LUA_CSUBSEP );
if ( filename = = NULL ) return 1 ; /* root not found */
funcname = mkfuncname ( L , name ) ;
if ( ( stat = ll_loadfunc ( L , filename , funcname ) ) ! = 0 ) {
if ( stat ! = ERRFUNC ) loaderror ( L , filename ) ; /* real error */
lua_pushfstring ( L , " \n \t no module " LUA_QS " in file " LUA_QS ,
name , filename ) ;
return 1 ; /* function not found */
if ( ( stat = loadfunc ( L , filename , name ) ) ! = 0 ) {
if ( stat ! = ERRFUNC )
return checkload ( L , 0 , filename ) ; /* real error */
else { /* open function not found */
lua_pushfstring ( L , " \n \t no module " LUA_QS " in file " LUA_QS ,
name , filename ) ;
return 1 ;
}
}
return 1 ;
lua_pushstring ( L , filename ) ; /* will be 2nd argument to module */
return 2 ;
}
static int load er_preload ( lua_State * L ) {
static int search er_preload ( lua_State * L ) {
const char * name = luaL_checkstring ( L , 1 ) ;
lua_getfield ( L , LUA_ENVIRONINDEX , " preload " ) ;
if ( ! lua_istable ( L , - 1 ) )
luaL_error ( L , LUA_QL ( " package.preload " ) " must be a table " ) ;
lua_getfield ( L , LUA_REGISTRYINDEX , " _PRELOAD " ) ;
lua_getfield ( L , - 1 , name ) ;
if ( lua_isnil ( L , - 1 ) ) /* not found? */
lua_pushfstring ( L , " \n \t no field package.preload['%s'] " , name ) ;
@ -444,48 +469,53 @@ static int loader_preload (lua_State *L) {
}
static const int sentinel_ = 0 ;
# define sentinel ((void *)&sentinel_)
static void findloader ( lua_State * L , const char * name ) {
int i ;
luaL_Buffer msg ; /* to build error message */
luaL_buffinit ( L , & msg ) ;
lua_getfield ( L , lua_upvalueindex ( 1 ) , " searchers " ) ; /* will be at index 3 */
if ( ! lua_istable ( L , 3 ) )
luaL_error ( L , LUA_QL ( " package.searchers " ) " must be a table " ) ;
/* iterate over available seachers to find a loader */
for ( i = 1 ; ; i + + ) {
lua_rawgeti ( L , 3 , i ) ; /* get a seacher */
if ( lua_isnil ( L , - 1 ) ) { /* no more searchers? */
lua_pop ( L , 1 ) ; /* remove nil */
luaL_pushresult ( & msg ) ; /* create error message */
luaL_error ( L , " module " LUA_QS " not found:%s " ,
name , lua_tostring ( L , - 1 ) ) ;
}
lua_pushstring ( L , name ) ;
lua_call ( L , 1 , 2 ) ; /* call it */
if ( lua_isfunction ( L , - 2 ) ) /* did it find a loader? */
return ; /* module loader found */
else if ( lua_isstring ( L , - 2 ) ) { /* searcher returned error message? */
lua_pop ( L , 1 ) ; /* remove extra return */
luaL_addvalue ( & msg ) ; /* concatenate error message */
}
else
lua_pop ( L , 2 ) ; /* remove both returns */
}
}
static int ll_require ( lua_State * L ) {
const char * name = luaL_checkstring ( L , 1 ) ;
int i ;
lua_settop ( L , 1 ) ; /* _LOADED table will be at index 2 */
lua_getfield ( L , LUA_REGISTRYINDEX , " _LOADED " ) ;
lua_getfield ( L , 2 , name ) ;
if ( lua_toboolean ( L , - 1 ) ) { /* is it there? */
if ( lua_touserdata ( L , - 1 ) = = sentinel ) /* check loops */
luaL_error ( L , " loop or previous error loading module " LUA_QS , name ) ;
lua_getfield ( L , 2 , name ) ; /* _LOADED[name] */
if ( lua_toboolean ( L , - 1 ) ) /* is it there? */
return 1 ; /* package is already loaded */
}
/* else must load it; iterate over available loaders */
lua_getfield ( L , LUA_ENVIRONINDEX , " loaders " ) ;
if ( ! lua_istable ( L , - 1 ) )
luaL_error ( L , LUA_QL ( " package.loaders " ) " must be a table " ) ;
lua_pushliteral ( L , " " ) ; /* error message accumulator */
for ( i = 1 ; ; i + + ) {
lua_rawgeti ( L , - 2 , i ) ; /* get a loader */
if ( lua_isnil ( L , - 1 ) )
luaL_error ( L , " module " LUA_QS " not found:%s " ,
name , lua_tostring ( L , - 2 ) ) ;
lua_pushstring ( L , name ) ;
lua_call ( L , 1 , 1 ) ; /* call it */
if ( lua_isfunction ( L , - 1 ) ) /* did it find module? */
break ; /* module loaded successfully */
else if ( lua_isstring ( L , - 1 ) ) /* loader returned error message? */
lua_concat ( L , 2 ) ; /* accumulate it */
else
lua_pop ( L , 1 ) ;
}
lua_pushlightuserdata ( L , sentinel ) ;
lua_setfield ( L , 2 , name ) ; /* _LOADED[name] = sentinel */
lua_pushstring ( L , name ) ; /* pass name as argument to module */
lua_call ( L , 1 , 1 ) ; /* run loaded module */
/* else must load package */
lua_pop ( L , 1 ) ; /* remove 'getfield' result */
findloader ( L , name ) ;
lua_pushstring ( L , name ) ; /* pass name as argument to module loader */
lua_insert ( L , - 2 ) ; /* name is 1st argument (before search data) */
lua_call ( L , 2 , 1 ) ; /* run loader to load module */
if ( ! lua_isnil ( L , - 1 ) ) /* non-nil return? */
lua_setfield ( L , 2 , name ) ; /* _LOADED[name] = returned value */
lua_getfield ( L , 2 , name ) ;
if ( lua_ touserdata ( L , - 1 ) = = sentinel ) { /* module did not set a value? */
if ( lua_isnil ( L , - 1 ) ) { /* module did not set a value? */
lua_pushboolean ( L , 1 ) ; /* use true as result */
lua_pushvalue ( L , - 1 ) ; /* extra copy to be returned */
lua_setfield ( L , 2 , name ) ; /* _LOADED[name] = true */
@ -502,26 +532,31 @@ static int ll_require (lua_State *L) {
* * ' module ' function
* * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# if defined(LUA_COMPAT_MODULE)
static void setfenv ( lua_State * L ) {
/*
* * changes the environment variable of calling function
*/
static void set_env ( lua_State * L ) {
lua_Debug ar ;
if ( lua_getstack ( L , 1 , & ar ) = = 0 | |
lua_getinfo ( L , " f " , & ar ) = = 0 | | /* get calling function */
lua_iscfunction ( L , - 1 ) )
luaL_error ( L , LUA_QL ( " module " ) " not called from a Lua function " ) ;
lua_pushvalue ( L , - 2 ) ;
lua_set fenv( L , - 2 ) ;
lua_pop ( L , 1 ) ;
lua_pushvalue ( L , - 2 ) ; /* copy new environment table to top */
lua_set upvalue( L , - 2 , 1 ) ;
lua_pop ( L , 1 ) ; /* remove function */
}
static void dooptions ( lua_State * L , int n ) {
int i ;
for ( i = 2 ; i < = n ; i + + ) {
lua_pushvalue ( L , i ) ; /* get option (a function) */
lua_pushvalue ( L , - 2 ) ; /* module */
lua_call ( L , 1 , 0 ) ;
if ( lua_isfunction ( L , i ) ) { /* avoid 'calling' extra info. */
lua_pushvalue ( L , i ) ; /* get option (a function) */
lua_pushvalue ( L , - 2 ) ; /* module */
lua_call ( L , 1 , 0 ) ;
}
}
}
@ -543,17 +578,8 @@ static void modinit (lua_State *L, const char *modname) {
static int ll_module ( lua_State * L ) {
const char * modname = luaL_checkstring ( L , 1 ) ;
int loaded = lua_gettop ( L ) + 1 ; /* index of _LOADED table */
lua_getfield ( L , LUA_REGISTRYINDEX , " _LOADED " ) ;
lua_getfield ( L , loaded , modname ) ; /* get _LOADED[modname] */
if ( ! lua_istable ( L , - 1 ) ) { /* not found? */
lua_pop ( L , 1 ) ; /* remove previous result */
/* try global variable (and create one if it does not exist) */
if ( luaL_findtable ( L , LUA_GLOBALSINDEX , modname , 1 ) ! = NULL )
return luaL_error ( L , " name conflict for module " LUA_QS , modname ) ;
lua_pushvalue ( L , - 1 ) ;
lua_setfield ( L , loaded , modname ) ; /* _LOADED[modname] = new table */
}
int lastarg = lua_gettop ( L ) ; /* last parameter */
luaL_pushmodule ( L , modname , 1 ) ; /* get/create module table */
/* check whether table already has a _NAME field */
lua_getfield ( L , - 1 , " _NAME " ) ;
if ( ! lua_isnil ( L , - 1 ) ) /* is table an initialized module? */
@ -563,9 +589,9 @@ static int ll_module (lua_State *L) {
modinit ( L , modname ) ;
}
lua_pushvalue ( L , - 1 ) ;
set f env( L ) ;
dooptions ( L , l oaded - 1 ) ;
return 0 ;
set _ env( L ) ;
dooptions ( L , l astarg ) ;
return 1 ;
}
@ -576,12 +602,12 @@ static int ll_seeall (lua_State *L) {
lua_pushvalue ( L , - 1 ) ;
lua_setmetatable ( L , 1 ) ;
}
lua_push value( L , LUA_GLOBALSINDEX ) ;
lua_push globaltable( L ) ;
lua_setfield ( L , - 2 , " __index " ) ; /* mt.__index = _G */
return 0 ;
}
# endif
/* }====================================================== */
@ -589,15 +615,30 @@ static int ll_seeall (lua_State *L) {
/* auxiliary mark (for internal use) */
# define AUXMARK "\1"
static void setpath ( lua_State * L , const char * fieldname , const char * envname ,
const char * def ) {
const char * path = getenv ( envname ) ;
/*
* * return registry . LUA_NOENV as a boolean
*/
static int noenv ( lua_State * L ) {
int b ;
lua_getfield ( L , LUA_REGISTRYINDEX , " LUA_NOENV " ) ;
b = lua_toboolean ( L , - 1 ) ;
lua_pop ( L , 1 ) ; /* remove value */
return b ;
}
static void setpath ( lua_State * L , const char * fieldname , const char * envname1 ,
const char * envname2 , const char * def ) {
const char * path = getenv ( envname1 ) ;
if ( path = = NULL ) /* no environment variable? */
path = getenv ( envname2 ) ; /* try alternative name */
if ( path = = NULL | | noenv ( L ) ) /* no environment variable? */
lua_pushstring ( L , def ) ; /* use default */
else {
/* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */
path = luaL_gsub ( L , path , LUA_PATHSEP LUA_PATHSEP ,
LUA_PATHSEP AUXMARK LUA_PATHSEP ) ;
path = luaL_gsub ( L , path , LUA_PATH _ SEP LUA_PATH _ SEP,
LUA_PATH _ SEP AUXMARK LUA_PATH _ SEP) ;
luaL_gsub ( L , path , AUXMARK , def ) ;
lua_remove ( L , - 2 ) ;
}
@ -608,59 +649,66 @@ static void setpath (lua_State *L, const char *fieldname, const char *envname,
static const luaL_Reg pk_funcs [ ] = {
{ " loadlib " , ll_loadlib } ,
{ " searchpath " , ll_searchpath } ,
# if defined(LUA_COMPAT_MODULE)
{ " seeall " , ll_seeall } ,
# endif
{ NULL , NULL }
} ;
static const luaL_Reg ll_funcs [ ] = {
# if defined(LUA_COMPAT_MODULE)
{ " module " , ll_module } ,
# endif
{ " require " , ll_require } ,
{ NULL , NULL }
} ;
static const lua_CFunction load ers[ ] =
{ loader_preload, loader_Lua , loader_C , load er_Croot, NULL } ;
static const lua_CFunction search ers[ ] =
{ searcher_preload, searcher_Lua , searcher_C , search er_Croot, NULL } ;
LUA LIB _API int luaopen_package ( lua_State * L ) {
LUA MOD _API int luaopen_package ( lua_State * L ) {
int i ;
/* create new type _LOADLIB */
luaL_newmetatable ( L , " _LOADLIB " ) ;
lua_pushcfunction ( L , gctm ) ;
lua_setfield ( L , - 2 , " __gc " ) ;
/* create `package' table */
luaL_register ( L , LUA_LOADLIBNAME , pk_funcs ) ;
# if defined(LUA_COMPAT_LOADLIB)
lua_getfield ( L , - 1 , " loadlib " ) ;
lua_setfield ( L , LUA_GLOBALSINDEX , " loadlib " ) ;
# endif
lua_pushvalue ( L , - 1 ) ;
lua_replace ( L , LUA_ENVIRONINDEX ) ;
/* create `loaders' table */
lua_createtable ( L , 0 , sizeof ( loaders ) / sizeof ( loaders [ 0 ] ) - 1 ) ;
/* fill it with pre-defined loaders */
for ( i = 0 ; loaders [ i ] ! = NULL ; i + + ) {
lua_pushcfunction ( L , loaders [ i ] ) ;
luaL_newlib ( L , pk_funcs ) ;
/* create 'searchers' table */
lua_createtable ( L , sizeof ( searchers ) / sizeof ( searchers [ 0 ] ) - 1 , 0 ) ;
/* fill it with pre-defined searchers */
for ( i = 0 ; searchers [ i ] ! = NULL ; i + + ) {
lua_pushvalue ( L , - 2 ) ; /* set 'package' as upvalue for all searchers */
lua_pushcclosure ( L , searchers [ i ] , 1 ) ;
lua_rawseti ( L , - 2 , i + 1 ) ;
}
lua_setfield ( L , - 2 , " loaders " ) ; /* put it in field `loaders' */
setpath ( L , " path " , LUA_PATH , LUA_PATH_DEFAULT ) ; /* set field `path' */
setpath ( L , " cpath " , LUA_CPATH , LUA_CPATH_DEFAULT ) ; /* set field `cpath' */
# if defined(LUA_COMPAT_LOADERS)
lua_pushvalue ( L , - 1 ) ; /* make a copy of 'searchers' table */
lua_setfield ( L , - 3 , " loaders " ) ; /* put it in field `loaders' */
# endif
lua_setfield ( L , - 2 , " searchers " ) ; /* put it in field 'searchers' */
/* set field 'path' */
setpath ( L , " path " , LUA_PATHVERSION , LUA_PATH , LUA_PATH_DEFAULT ) ;
/* set field 'cpath' */
setpath ( L , " cpath " , LUA_CPATHVERSION , LUA_CPATH , LUA_CPATH_DEFAULT ) ;
/* store config information */
lua_pushliteral ( L , LUA_DIRSEP " \n " LUA_PATHSEP " \n " LUA_PATH_MARK " \n "
LUA_EXECDIR " \n " LUA_IGMARK ) ;
lua_pushliteral ( L , LUA_DIRSEP " \n " LUA_PATH _ SEP " \n " LUA_PATH_MARK " \n "
LUA_EXEC _ DIR " \n " LUA_IGMARK " \n " ) ;
lua_setfield ( L , - 2 , " config " ) ;
/* set field `loaded' */
luaL_findtable ( L , LUA_REGISTRYINDEX , " _LOADED " , 2 ) ;
luaL_ getsub table( L , LUA_REGISTRYINDEX , " _LOADED " ) ;
lua_setfield ( L , - 2 , " loaded " ) ;
/* set field `preload' */
lua _newtable( L ) ;
lua L_getsubtable( L , LUA_REGISTRYINDEX , " _PRELOAD " ) ;
lua_setfield ( L , - 2 , " preload " ) ;
lua_pushvalue ( L , LUA_GLOBALSINDEX ) ;
luaL_register ( L , NULL , ll_funcs ) ; /* open lib into global table */
lua_pop ( L , 1 ) ;
lua_pushglobaltable ( L ) ;
lua_pushvalue ( L , - 2 ) ; /* set 'package' as upvalue for next lib */
luaL_setfuncs ( L , ll_funcs , 1 ) ; /* open lib into global table */
lua_pop ( L , 1 ) ; /* pop global table */
return 1 ; /* return 'package' table */
}