#define loadlib_c
#define LUA_LIB
#include "lprefix.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#if !defined(LUA_PATH_VAR)
#define LUA_PATH_VAR "LUA_PATH"
#endif
#if !defined(LUA_CPATH_VAR)
#define LUA_CPATH_VAR "LUA_CPATH"
#endif
#define LUA_PATHSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
#define LUA_PATHVARVERSION LUA_PATH_VAR LUA_PATHSUFFIX
#define LUA_CPATHVARVERSION LUA_CPATH_VAR LUA_PATHSUFFIX
#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
#if !defined(LUA_CSUBSEP)
#define LUA_CSUBSEP LUA_DIRSEP
#endif
#if !defined(LUA_LSUBSEP)
#define LUA_LSUBSEP LUA_DIRSEP
#endif
#define LUA_POF "luaopen_"
#define LUA_OFSEP "_"
static
const
int
CLIBS = 0;
#define LIB_FAIL "open"
#define setprogdir(L) ((void)0)
static
void
lsys_unloadlib (
void
*lib);
static
void
*lsys_load (lua_State *L,
const
char
*path,
int
seeglb);
static
lua_CFunction lsys_sym (lua_State *L,
void
*lib,
const
char
*sym);
#if defined(LUA_USE_DLOPEN) /* { */
#include <dlfcn.h>
#if defined(__GNUC__)
#define cast_func(p) (__extension__ (lua_CFunction)(p))
#else
#define cast_func(p) ((lua_CFunction)(p))
#endif
static
void
lsys_unloadlib (
void
*lib) {
dlclose(lib);
}
static
void
*lsys_load (lua_State *L,
const
char
*path,
int
seeglb) {
void
*lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL));
if
(lib == NULL) marpa_lua_pushstring(L, dlerror());
return
lib;
}
static
lua_CFunction lsys_sym (lua_State *L,
void
*lib,
const
char
*sym) {
lua_CFunction f = cast_func(dlsym(lib, sym));
if
(f == NULL) marpa_lua_pushstring(L, dlerror());
return
f;
}
#elif defined(LUA_DL_DLL) /* }{ */
#include <windows.h>
#undef setprogdir
#if !defined(LUA_LLE_FLAGS)
#define LUA_LLE_FLAGS 0
#endif
static
void
setprogdir (lua_State *L) {
char
buff[MAX_PATH + 1];
char
*lb;
DWORD
nsize =
sizeof
(buff)/
sizeof
(
char
);
DWORD
n = GetModuleFileNameA(NULL, buff, nsize);
if
(n == 0 || n == nsize || (lb =
strrchr
(buff,
'\\'
)) == NULL)
marpa_luaL_error(L,
"unable to get ModuleFileName"
);
else
{
*lb =
'\0'
;
marpa_luaL_gsub(L, marpa_lua_tostring(L, -1), LUA_EXEC_DIR, buff);
marpa_lua_remove(L, -2);
}
}
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)/
sizeof
(
char
), NULL))
marpa_lua_pushstring(L, buffer);
else
marpa_lua_pushfstring(L,
"system error %d\n"
, error);
}
static
void
lsys_unloadlib (
void
*lib) {
FreeLibrary((
HMODULE
)lib);
}
static
void
*lsys_load (lua_State *L,
const
char
*path,
int
seeglb) {
HMODULE
lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS);
(
void
)(seeglb);
if
(lib == NULL) pusherror(L);
return
lib;
}
static
lua_CFunction lsys_sym (lua_State *L,
void
*lib,
const
char
*sym) {
lua_CFunction f = (lua_CFunction)GetProcAddress((
HMODULE
)lib, sym);
if
(f == NULL) pusherror(L);
return
f;
}
#else /* }{ */
#undef LIB_FAIL
#define LIB_FAIL "absent"
#define DLMSG "dynamic libraries not enabled; check your Lua installation"
static
void
lsys_unloadlib (
void
*lib) {
(
void
)(lib);
}
static
void
*lsys_load (lua_State *L,
const
char
*path,
int
seeglb) {
(
void
)(path); (
void
)(seeglb);
marpa_lua_pushliteral(L, DLMSG);
return
NULL;
}
static
lua_CFunction lsys_sym (lua_State *L,
void
*lib,
const
char
*sym) {
(
void
)(lib); (
void
)(sym);
marpa_lua_pushliteral(L, DLMSG);
return
NULL;
}
#endif /* } */
static
void
*checkclib (lua_State *L,
const
char
*path) {
void
*plib;
marpa_lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS);
marpa_lua_getfield(L, -1, path);
plib = marpa_lua_touserdata(L, -1);
marpa_lua_pop(L, 2);
return
plib;
}
static
void
addtoclib (lua_State *L,
const
char
*path,
void
*plib) {
marpa_lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS);
marpa_lua_pushlightuserdata(L, plib);
marpa_lua_pushvalue(L, -1);
marpa_lua_setfield(L, -3, path);
marpa_lua_rawseti(L, -2, marpa_luaL_len(L, -2) + 1);
marpa_lua_pop(L, 1);
}
static
int
gctm (lua_State *L) {
lua_Integer n = marpa_luaL_len(L, 1);
for
(; n >= 1; n--) {
marpa_lua_rawgeti(L, 1, n);
lsys_unloadlib(marpa_lua_touserdata(L, -1));
marpa_lua_pop(L, 1);
}
return
0;
}
#define ERRLIB 1
#define ERRFUNC 2
static
int
lookforfunc (lua_State *L,
const
char
*path,
const
char
*sym) {
void
*reg = checkclib(L, path);
if
(reg == NULL) {
reg = lsys_load(L, path, *sym ==
'*'
);
if
(reg == NULL)
return
ERRLIB;
addtoclib(L, path, reg);
}
if
(*sym ==
'*'
) {
marpa_lua_pushboolean(L, 1);
return
0;
}
else
{
lua_CFunction f = lsys_sym(L, reg, sym);
if
(f == NULL)
return
ERRFUNC;
marpa_lua_pushcfunction(L, f);
return
0;
}
}
static
int
ll_loadlib (lua_State *L) {
const
char
*path = marpa_luaL_checkstring(L, 1);
const
char
*init = marpa_luaL_checkstring(L, 2);
int
stat = lookforfunc(L, path, init);
if
(stat == 0)
return
1;
else
{
marpa_lua_pushnil(L);
marpa_lua_insert(L, -2);
marpa_lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL :
"init"
);
return
3;
}
}
static
int
readable (
const
char
*filename) {
FILE
*f =
fopen
(filename,
"r"
);
if
(f == NULL)
return
0;
fclose
(f);
return
1;
}
static
const
char
*pushnexttemplate (lua_State *L,
const
char
*path) {
const
char
*l;
while
(*path == *LUA_PATH_SEP) path++;
if
(*path ==
'\0'
)
return
NULL;
l =
strchr
(path, *LUA_PATH_SEP);
if
(l == NULL) l = path +
strlen
(path);
marpa_lua_pushlstring(L, path, l - path);
return
l;
}
static
const
char
*searchpath (lua_State *L,
const
char
*name,
const
char
*path,
const
char
*sep,
const
char
*dirsep) {
luaL_Buffer msg;
marpa_luaL_buffinit(L, &msg);
if
(*sep !=
'\0'
)
name = marpa_luaL_gsub(L, name, sep, dirsep);
while
((path = pushnexttemplate(L, path)) != NULL) {
const
char
*filename = marpa_luaL_gsub(L, marpa_lua_tostring(L, -1),
LUA_PATH_MARK, name);
marpa_lua_remove(L, -2);
if
(readable(filename))
return
filename;
marpa_lua_pushfstring(L,
"\n\tno file '%s'"
, filename);
marpa_lua_remove(L, -2);
marpa_luaL_addvalue(&msg);
}
marpa_luaL_pushresult(&msg);
return
NULL;
}
static
int
ll_searchpath (lua_State *L) {
const
char
*f = searchpath(L, marpa_luaL_checkstring(L, 1),
marpa_luaL_checkstring(L, 2),
marpa_luaL_optstring(L, 3,
"."
),
marpa_luaL_optstring(L, 4, LUA_DIRSEP));
if
(f != NULL)
return
1;
else
{
marpa_lua_pushnil(L);
marpa_lua_insert(L, -2);
return
2;
}
}
static
const
char
*findfile (lua_State *L,
const
char
*name,
const
char
*pname,
const
char
*dirsep) {
const
char
*path;
marpa_lua_getfield(L, marpa_lua_upvalueindex(1), pname);
path = marpa_lua_tostring(L, -1);
if
(path == NULL)
marpa_luaL_error(L,
"'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) {
marpa_lua_pushstring(L, filename);
return
2;
}
else
return
marpa_luaL_error(L,
"error loading module '%s' from file '%s':\n\t%s"
,
marpa_lua_tostring(L, 1), filename, marpa_lua_tostring(L, -1));
}
static
int
searcher_Lua (lua_State *L) {
const
char
*filename;
const
char
*name = marpa_luaL_checkstring(L, 1);
filename = findfile(L, name,
"path"
, LUA_LSUBSEP);
if
(filename == NULL)
return
1;
return
checkload(L, (marpa_luaL_loadfile(L, filename) == LUA_OK), filename);
}
static
int
loadfunc (lua_State *L,
const
char
*filename,
const
char
*modname) {
const
char
*openfunc;
const
char
*mark;
modname = marpa_luaL_gsub(L, modname,
"."
, LUA_OFSEP);
mark =
strchr
(modname, *LUA_IGMARK);
if
(mark) {
int
stat;
openfunc = marpa_lua_pushlstring(L, modname, mark - modname);
openfunc = marpa_lua_pushfstring(L, LUA_POF
"%s"
, openfunc);
stat = lookforfunc(L, filename, openfunc);
if
(stat != ERRFUNC)
return
stat;
modname = mark + 1;
}
openfunc = marpa_lua_pushfstring(L, LUA_POF
"%s"
, modname);
return
lookforfunc(L, filename, openfunc);
}
static
int
searcher_C (lua_State *L) {
const
char
*name = marpa_luaL_checkstring(L, 1);
const
char
*filename = findfile(L, name,
"cpath"
, LUA_CSUBSEP);
if
(filename == NULL)
return
1;
return
checkload(L, (loadfunc(L, filename, name) == 0), filename);
}
static
int
searcher_Croot (lua_State *L) {
const
char
*filename;
const
char
*name = marpa_luaL_checkstring(L, 1);
const
char
*p =
strchr
(name,
'.'
);
int
stat;
if
(p == NULL)
return
0;
marpa_lua_pushlstring(L, name, p - name);
filename = findfile(L, marpa_lua_tostring(L, -1),
"cpath"
, LUA_CSUBSEP);
if
(filename == NULL)
return
1;
if
((stat = loadfunc(L, filename, name)) != 0) {
if
(stat != ERRFUNC)
return
checkload(L, 0, filename);
else
{
marpa_lua_pushfstring(L,
"\n\tno module '%s' in file '%s'"
, name, filename);
return
1;
}
}
marpa_lua_pushstring(L, filename);
return
2;
}
static
int
searcher_preload (lua_State *L) {
const
char
*name = marpa_luaL_checkstring(L, 1);
marpa_lua_getfield(L, LUA_REGISTRYINDEX,
"_PRELOAD"
);
if
(marpa_lua_getfield(L, -1, name) == LUA_TNIL)
marpa_lua_pushfstring(L,
"\n\tno field package.preload['%s']"
, name);
return
1;
}
static
void
findloader (lua_State *L,
const
char
*name) {
int
i;
luaL_Buffer msg;
marpa_luaL_buffinit(L, &msg);
if
(marpa_lua_getfield(L, marpa_lua_upvalueindex(1),
"searchers"
) != LUA_TTABLE)
marpa_luaL_error(L,
"'package.searchers' must be a table"
);
for
(i = 1; ; i++) {
if
(marpa_lua_rawgeti(L, 3, i) == LUA_TNIL) {
marpa_lua_pop(L, 1);
marpa_luaL_pushresult(&msg);
marpa_luaL_error(L,
"module '%s' not found:%s"
, name, marpa_lua_tostring(L, -1));
}
marpa_lua_pushstring(L, name);
marpa_lua_call(L, 1, 2);
if
(marpa_lua_isfunction(L, -2))
return
;
else
if
(marpa_lua_isstring(L, -2)) {
marpa_lua_pop(L, 1);
marpa_luaL_addvalue(&msg);
}
else
marpa_lua_pop(L, 2);
}
}
static
int
ll_require (lua_State *L) {
const
char
*name = marpa_luaL_checkstring(L, 1);
marpa_lua_settop(L, 1);
marpa_lua_getfield(L, LUA_REGISTRYINDEX,
"_LOADED"
);
marpa_lua_getfield(L, 2, name);
if
(marpa_lua_toboolean(L, -1))
return
1;
marpa_lua_pop(L, 1);
findloader(L, name);
marpa_lua_pushstring(L, name);
marpa_lua_insert(L, -2);
marpa_lua_call(L, 2, 1);
if
(!marpa_lua_isnil(L, -1))
marpa_lua_setfield(L, 2, name);
if
(marpa_lua_getfield(L, 2, name) == LUA_TNIL) {
marpa_lua_pushboolean(L, 1);
marpa_lua_pushvalue(L, -1);
marpa_lua_setfield(L, 2, name);
}
return
1;
}
#if defined(LUA_COMPAT_MODULE)
static
void
set_env (lua_State *L) {
lua_Debug ar;
if
(marpa_lua_getstack(L, 1, &ar) == 0 ||
marpa_lua_getinfo(L,
"f"
, &ar) == 0 ||
marpa_lua_iscfunction(L, -1))
marpa_luaL_error(L,
"'module' not called from a Lua function"
);
marpa_lua_pushvalue(L, -2);
marpa_lua_setupvalue(L, -2, 1);
marpa_lua_pop(L, 1);
}
static
void
dooptions (lua_State *L,
int
n) {
int
i;
for
(i = 2; i <= n; i++) {
if
(marpa_lua_isfunction(L, i)) {
marpa_lua_pushvalue(L, i);
marpa_lua_pushvalue(L, -2);
marpa_lua_call(L, 1, 0);
}
}
}
static
void
modinit (lua_State *L,
const
char
*modname) {
const
char
*dot;
marpa_lua_pushvalue(L, -1);
marpa_lua_setfield(L, -2,
"_M"
);
marpa_lua_pushstring(L, modname);
marpa_lua_setfield(L, -2,
"_NAME"
);
dot =
strrchr
(modname,
'.'
);
if
(dot == NULL) dot = modname;
else
dot++;
marpa_lua_pushlstring(L, modname, dot - modname);
marpa_lua_setfield(L, -2,
"_PACKAGE"
);
}
static
int
ll_module (lua_State *L) {
const
char
*modname = marpa_luaL_checkstring(L, 1);
int
lastarg = marpa_lua_gettop(L);
luaL_pushmodule(L, modname, 1);
if
(marpa_lua_getfield(L, -1,
"_NAME"
) != LUA_TNIL)
marpa_lua_pop(L, 1);
else
{
marpa_lua_pop(L, 1);
modinit(L, modname);
}
marpa_lua_pushvalue(L, -1);
set_env(L);
dooptions(L, lastarg);
return
1;
}
static
int
ll_seeall (lua_State *L) {
marpa_luaL_checktype(L, 1, LUA_TTABLE);
if
(!marpa_lua_getmetatable(L, 1)) {
marpa_lua_createtable(L, 0, 1);
marpa_lua_pushvalue(L, -1);
marpa_lua_setmetatable(L, 1);
}
marpa_lua_pushglobaltable(L);
marpa_lua_setfield(L, -2,
"__index"
);
return
0;
}
#endif
#define AUXMARK "\1"
static
int
noenv (lua_State *L) {
int
b;
marpa_lua_getfield(L, LUA_REGISTRYINDEX,
"LUA_NOENV"
);
b = marpa_lua_toboolean(L, -1);
marpa_lua_pop(L, 1);
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)
path =
getenv
(envname2);
if
(path == NULL || noenv(L))
marpa_lua_pushstring(L, def);
else
{
path = marpa_luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP,
LUA_PATH_SEP AUXMARK LUA_PATH_SEP);
marpa_luaL_gsub(L, path, AUXMARK, def);
marpa_lua_remove(L, -2);
}
setprogdir(L);
marpa_lua_setfield(L, -2, fieldname);
}
static
const
luaL_Reg pk_funcs[] = {
{
"loadlib"
, ll_loadlib},
{
"searchpath"
, ll_searchpath},
#if defined(LUA_COMPAT_MODULE)
{
"seeall"
, ll_seeall},
#endif
{
"preload"
, NULL},
{
"cpath"
, NULL},
{
"path"
, NULL},
{
"searchers"
, NULL},
{
"loaded"
, NULL},
{NULL, NULL}
};
static
const
luaL_Reg ll_funcs[] = {
#if defined(LUA_COMPAT_MODULE)
{
"module"
, ll_module},
#endif
{
"require"
, ll_require},
{NULL, NULL}
};
static
void
createsearcherstable (lua_State *L) {
static
const
lua_CFunction searchers[] =
{searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL};
int
i;
marpa_lua_createtable(L,
sizeof
(searchers)/
sizeof
(searchers[0]) - 1, 0);
for
(i=0; searchers[i] != NULL; i++) {
marpa_lua_pushvalue(L, -2);
marpa_lua_pushcclosure(L, searchers[i], 1);
marpa_lua_rawseti(L, -2, i+1);
}
#if defined(LUA_COMPAT_LOADERS)
marpa_lua_pushvalue(L, -1);
marpa_lua_setfield(L, -3,
"loaders"
);
#endif
marpa_lua_setfield(L, -2,
"searchers"
);
}
static
void
createclibstable (lua_State *L) {
marpa_lua_newtable(L);
marpa_lua_createtable(L, 0, 1);
marpa_lua_pushcfunction(L, gctm);
marpa_lua_setfield(L, -2,
"__gc"
);
marpa_lua_setmetatable(L, -2);
marpa_lua_rawsetp(L, LUA_REGISTRYINDEX, &CLIBS);
}
LUAMOD_API
int
marpa_luaopen_package (lua_State *L) {
createclibstable(L);
marpa_luaL_newlib(L, pk_funcs);
createsearcherstable(L);
setpath(L,
"path"
, LUA_PATHVARVERSION, LUA_PATH_VAR, LUA_PATH_DEFAULT);
setpath(L,
"cpath"
, LUA_CPATHVARVERSION, LUA_CPATH_VAR, LUA_CPATH_DEFAULT);
marpa_lua_pushliteral(L, LUA_DIRSEP
"\n"
LUA_PATH_SEP
"\n"
LUA_PATH_MARK
"\n"
LUA_EXEC_DIR
"\n"
LUA_IGMARK
"\n"
);
marpa_lua_setfield(L, -2,
"config"
);
marpa_luaL_getsubtable(L, LUA_REGISTRYINDEX,
"_LOADED"
);
marpa_lua_setfield(L, -2,
"loaded"
);
marpa_luaL_getsubtable(L, LUA_REGISTRYINDEX,
"_PRELOAD"
);
marpa_lua_setfield(L, -2,
"preload"
);
marpa_lua_pushglobaltable(L);
marpa_lua_pushvalue(L, -2);
marpa_luaL_setfuncs(L, ll_funcs, 1);
marpa_lua_pop(L, 1);
return
1;
}