|
|
@ -1,5 +1,5 @@ |
|
|
|
/*
|
|
|
|
** $Id: lbaselib.c,v 1.221 2009/10/23 19:12:19 roberto Exp roberto $ |
|
|
|
** $Id: lbaselib.c,v 1.222 2009/11/09 18:55:17 roberto Exp roberto $ |
|
|
|
** Basic library |
|
|
|
** See Copyright Notice in lua.h |
|
|
|
*/ |
|
|
@ -276,13 +276,11 @@ static int luaB_loadfile (lua_State *L) { |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Reader for generic `load' function: `lua_load' uses the |
|
|
|
** stack for internal stuff, so the reader cannot change the |
|
|
|
** stack top. Instead, it keeps its resulting string in a |
|
|
|
** reserved slot inside the stack. |
|
|
|
** {====================================================== |
|
|
|
** Generic Read function |
|
|
|
** ======================================================= |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
static const char *checkrights (lua_State *L, const char *mode, const char *s) { |
|
|
|
if (strchr(mode, 'b') == NULL && *s == LUA_SIGNATURE[0]) |
|
|
|
return lua_pushstring(L, "attempt to load a binary chunk"); |
|
|
@ -292,24 +290,42 @@ static const char *checkrights (lua_State *L, const char *mode, const char *s) { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
** reserves a slot, above all arguments, to hold a copy of the returned |
|
|
|
** string to avoid it being collected while parsed |
|
|
|
*/ |
|
|
|
#define RESERVEDSLOT 4 |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Reader for generic `load' function: `lua_load' uses the |
|
|
|
** stack for internal stuff, so the reader cannot change the |
|
|
|
** stack top. Instead, it keeps its resulting string in a |
|
|
|
** reserved slot inside the stack. |
|
|
|
*/ |
|
|
|
typedef struct { /* reader state */ |
|
|
|
int f; /* position of reader function on stack */ |
|
|
|
const char *mode; /* allowed modes (binary/text) */ |
|
|
|
} Readstat; |
|
|
|
|
|
|
|
static const char *generic_reader (lua_State *L, void *ud, size_t *size) { |
|
|
|
const char *s; |
|
|
|
const char **mode = (const char **)ud; |
|
|
|
Readstat *stat = (Readstat *)ud; |
|
|
|
luaL_checkstack(L, 2, "too many nested functions"); |
|
|
|
lua_pushvalue(L, 1); /* get function */ |
|
|
|
lua_pushvalue(L, stat->f); /* get function */ |
|
|
|
lua_call(L, 0, 1); /* call it */ |
|
|
|
if (lua_isnil(L, -1)) { |
|
|
|
*size = 0; |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
else if ((s = lua_tostring(L, -1)) != NULL) { |
|
|
|
if (*mode != NULL) { /* first time? */ |
|
|
|
s = checkrights(L, *mode, s); /* check whether chunk format is allowed */ |
|
|
|
*mode = NULL; /* to avoid further checks */ |
|
|
|
if (stat->mode != NULL) { /* first time? */ |
|
|
|
s = checkrights(L, stat->mode, s); /* check mode */ |
|
|
|
stat->mode = NULL; /* to avoid further checks */ |
|
|
|
if (s) luaL_error(L, s); |
|
|
|
} |
|
|
|
lua_replace(L, 3); /* save string in a reserved stack slot */ |
|
|
|
return lua_tolstring(L, 3, size); |
|
|
|
lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ |
|
|
|
return lua_tolstring(L, RESERVEDSLOT, size); |
|
|
|
} |
|
|
|
else { |
|
|
|
luaL_error(L, "reader function must return a string"); |
|
|
@ -318,30 +334,51 @@ static const char *generic_reader (lua_State *L, void *ud, size_t *size) { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int luaB_load (lua_State *L) { |
|
|
|
static int luaB_load_aux (lua_State *L, int farg) { |
|
|
|
int status; |
|
|
|
const char *s = lua_tostring(L, 1); |
|
|
|
const char *mode = luaL_optstring(L, 3, "bt"); |
|
|
|
Readstat stat; |
|
|
|
const char *s = lua_tostring(L, farg); |
|
|
|
stat.mode = luaL_optstring(L, farg + 2, "bt"); |
|
|
|
if (s != NULL) { /* loading a string? */ |
|
|
|
const char *chunkname = luaL_optstring(L, 2, s); |
|
|
|
status = (checkrights(L, mode, s) != NULL) |
|
|
|
|| luaL_loadbuffer(L, s, lua_objlen(L, 1), chunkname); |
|
|
|
const char *chunkname = luaL_optstring(L, farg + 1, s); |
|
|
|
status = (checkrights(L, stat.mode, s) != NULL) |
|
|
|
|| luaL_loadbuffer(L, s, lua_objlen(L, farg), chunkname); |
|
|
|
} |
|
|
|
else { /* loading from a reader function */ |
|
|
|
const char *chunkname = luaL_optstring(L, 2, "=(load)"); |
|
|
|
luaL_checktype(L, 1, LUA_TFUNCTION); |
|
|
|
lua_settop(L, 3); /* function, eventual name, plus one reserved slot */ |
|
|
|
status = lua_load(L, generic_reader, &mode, chunkname); |
|
|
|
const char *chunkname = luaL_optstring(L, farg + 1, "=(load)"); |
|
|
|
luaL_checktype(L, farg, LUA_TFUNCTION); |
|
|
|
stat.f = farg; |
|
|
|
lua_settop(L, RESERVEDSLOT); /* create reserved slot */ |
|
|
|
status = lua_load(L, generic_reader, &stat, chunkname); |
|
|
|
} |
|
|
|
return load_aux(L, status); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int luaB_load (lua_State *L) { |
|
|
|
return luaB_load_aux(L, 1); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int luaB_loadin (lua_State *L) { |
|
|
|
int n; |
|
|
|
luaL_checktype(L, 1, LUA_TTABLE); |
|
|
|
n = luaB_load_aux(L, 2); |
|
|
|
if (n == 1) { /* success? */ |
|
|
|
lua_pushvalue(L, 1); /* environment for loaded function */ |
|
|
|
lua_setfenv(L, -2); |
|
|
|
} |
|
|
|
return n; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int luaB_loadstring (lua_State *L) { |
|
|
|
lua_settop(L, 2); |
|
|
|
lua_pushliteral(L, "tb"); |
|
|
|
return luaB_load(L); /* dostring(s, n) == load(s, n, "tb") */ |
|
|
|
|
|
|
|
} |
|
|
|
/* }====================================================== */ |
|
|
|
|
|
|
|
|
|
|
|
static int dofilecont (lua_State *L) { |
|
|
@ -481,6 +518,7 @@ static const luaL_Reg base_funcs[] = { |
|
|
|
{"getmetatable", luaB_getmetatable}, |
|
|
|
{"loadfile", luaB_loadfile}, |
|
|
|
{"load", luaB_load}, |
|
|
|
{"loadin", luaB_loadin}, |
|
|
|
{"loadstring", luaB_loadstring}, |
|
|
|
{"next", luaB_next}, |
|
|
|
{"pcall", luaB_pcall}, |
|
|
|