summaryrefslogtreecommitdiffstats
path: root/lua/lauxlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'lua/lauxlib.c')
-rw-r--r--lua/lauxlib.c343
1 files changed, 202 insertions, 141 deletions
diff --git a/lua/lauxlib.c b/lua/lauxlib.c
index b00f8c7..5d362c3 100644
--- a/lua/lauxlib.c
+++ b/lua/lauxlib.c
@@ -1,9 +1,14 @@
/*
-** $Id: lauxlib.c,v 1.248.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lauxlib.c,v 1.284 2015/11/19 19:16:22 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
+#define lauxlib_c
+#define LUA_LIB
+
+#include "lprefix.h"
+
#include <errno.h>
#include <stdarg.h>
@@ -16,9 +21,6 @@
** Any function declared here could be written as an application function.
*/
-#define lauxlib_c
-#define LUA_LIB
-
#include "lua.h"
#include "lauxlib.h"
@@ -31,8 +33,8 @@
*/
-#define LEVELS1 12 /* size of the first part of the stack */
-#define LEVELS2 10 /* size of the second part of the stack */
+#define LEVELS1 10 /* size of the first part of the stack */
+#define LEVELS2 11 /* size of the second part of the stack */
@@ -64,11 +66,20 @@ static int findfield (lua_State *L, int objidx, int level) {
}
+/*
+** Search for a name for a function in all loaded modules
+** (registry._LOADED).
+*/
static int pushglobalfuncname (lua_State *L, lua_Debug *ar) {
int top = lua_gettop(L);
lua_getinfo(L, "f", ar); /* push function */
- lua_pushglobaltable(L);
+ lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
if (findfield(L, top + 1, 2)) {
+ const char *name = lua_tostring(L, -1);
+ if (strncmp(name, "_G.", 3) == 0) { /* name start with '_G.'? */
+ lua_pushstring(L, name + 3); /* push name without prefix */
+ lua_remove(L, -2); /* remove original name */
+ }
lua_copy(L, -1, top + 1); /* move name to proper place */
lua_pop(L, 2); /* remove pushed values */
return 1;
@@ -81,24 +92,22 @@ static int pushglobalfuncname (lua_State *L, lua_Debug *ar) {
static void pushfuncname (lua_State *L, lua_Debug *ar) {
- if (*ar->namewhat != '\0') /* is there a name? */
- lua_pushfstring(L, "function " LUA_QS, ar->name);
+ if (pushglobalfuncname(L, ar)) { /* try first a global name */
+ lua_pushfstring(L, "function '%s'", lua_tostring(L, -1));
+ lua_remove(L, -2); /* remove name */
+ }
+ else if (*ar->namewhat != '\0') /* is there a name from code? */
+ lua_pushfstring(L, "%s '%s'", ar->namewhat, ar->name); /* use it */
else if (*ar->what == 'm') /* main? */
lua_pushliteral(L, "main chunk");
- else if (*ar->what == 'C') {
- if (pushglobalfuncname(L, ar)) {
- lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1));
- lua_remove(L, -2); /* remove name */
- }
- else
- lua_pushliteral(L, "?");
- }
- else
+ else if (*ar->what != 'C') /* for Lua functions, use <file:line> */
lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined);
+ else /* nothing left... */
+ lua_pushliteral(L, "?");
}
-static int countlevels (lua_State *L) {
+static int lastlevel (lua_State *L) {
lua_Debug ar;
int li = 1, le = 1;
/* find an upper bound */
@@ -117,14 +126,16 @@ LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1,
const char *msg, int level) {
lua_Debug ar;
int top = lua_gettop(L);
- int numlevels = countlevels(L1);
- int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0;
- if (msg) lua_pushfstring(L, "%s\n", msg);
+ int last = lastlevel(L1);
+ int n1 = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1;
+ if (msg)
+ lua_pushfstring(L, "%s\n", msg);
+ luaL_checkstack(L, 10, NULL);
lua_pushliteral(L, "stack traceback:");
while (lua_getstack(L1, level++, &ar)) {
- if (level == mark) { /* too many levels? */
+ if (n1-- == 0) { /* too many levels? */
lua_pushliteral(L, "\n\t..."); /* add a '...' */
- level = numlevels - LEVELS2; /* and skip to last ones */
+ level = last - LEVELS2 + 1; /* and skip to last ones */
}
else {
lua_getinfo(L1, "Slnt", &ar);
@@ -150,33 +161,40 @@ LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1,
** =======================================================
*/
-LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {
+LUALIB_API int luaL_argerror (lua_State *L, int arg, const char *extramsg) {
lua_Debug ar;
if (!lua_getstack(L, 0, &ar)) /* no stack frame? */
- return luaL_error(L, "bad argument #%d (%s)", narg, extramsg);
+ return luaL_error(L, "bad argument #%d (%s)", arg, extramsg);
lua_getinfo(L, "n", &ar);
if (strcmp(ar.namewhat, "method") == 0) {
- narg--; /* do not count `self' */
- if (narg == 0) /* error is in the self argument itself? */
- return luaL_error(L, "calling " LUA_QS " on bad self (%s)",
+ arg--; /* do not count 'self' */
+ if (arg == 0) /* error is in the self argument itself? */
+ return luaL_error(L, "calling '%s' on bad self (%s)",
ar.name, extramsg);
}
if (ar.name == NULL)
ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?";
- return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)",
- narg, ar.name, extramsg);
+ return luaL_error(L, "bad argument #%d to '%s' (%s)",
+ arg, ar.name, extramsg);
}
-static int typeerror (lua_State *L, int narg, const char *tname) {
- const char *msg = lua_pushfstring(L, "%s expected, got %s",
- tname, luaL_typename(L, narg));
- return luaL_argerror(L, narg, msg);
+static int typeerror (lua_State *L, int arg, const char *tname) {
+ const char *msg;
+ const char *typearg; /* name for the type of the actual argument */
+ if (luaL_getmetafield(L, arg, "__name") == LUA_TSTRING)
+ typearg = lua_tostring(L, -1); /* use the given type name */
+ else if (lua_type(L, arg) == LUA_TLIGHTUSERDATA)
+ typearg = "light userdata"; /* special name for messages */
+ else
+ typearg = luaL_typename(L, arg); /* standard name */
+ msg = lua_pushfstring(L, "%s expected, got %s", tname, typearg);
+ return luaL_argerror(L, arg, msg);
}
-static void tag_error (lua_State *L, int narg, int tag) {
- typeerror(L, narg, lua_typename(L, tag));
+static void tag_error (lua_State *L, int arg, int tag) {
+ typeerror(L, arg, lua_typename(L, tag));
}
@@ -222,7 +240,7 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
}
-#if !defined(inspectstat) /* { */
+#if !defined(l_inspectstat) /* { */
#if defined(LUA_USE_POSIX)
@@ -231,13 +249,13 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
/*
** use appropriate macros to interpret 'pclose' return status
*/
-#define inspectstat(stat,what) \
+#define l_inspectstat(stat,what) \
if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \
else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; }
#else
-#define inspectstat(stat,what) /* no op */
+#define l_inspectstat(stat,what) /* no op */
#endif
@@ -249,7 +267,7 @@ LUALIB_API int luaL_execresult (lua_State *L, int stat) {
if (stat == -1) /* error? */
return luaL_fileresult(L, 0, NULL);
else {
- inspectstat(stat, what); /* interpret result */
+ l_inspectstat(stat, what); /* interpret result */
if (*what == 'e' && stat == 0) /* successful termination? */
lua_pushboolean(L, 1);
else
@@ -270,11 +288,12 @@ LUALIB_API int luaL_execresult (lua_State *L, int stat) {
*/
LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
- luaL_getmetatable(L, tname); /* try to get metatable */
- if (!lua_isnil(L, -1)) /* name already in use? */
+ if (luaL_getmetatable(L, tname) != LUA_TNIL) /* name already in use? */
return 0; /* leave previous value on top, but return 0 */
lua_pop(L, 1);
- lua_newtable(L); /* create metatable */
+ lua_createtable(L, 0, 2); /* create metatable */
+ lua_pushstring(L, tname);
+ lua_setfield(L, -2, "__name"); /* metatable.__name = tname */
lua_pushvalue(L, -1);
lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */
return 1;
@@ -317,16 +336,16 @@ LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
** =======================================================
*/
-LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def,
+LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def,
const char *const lst[]) {
- const char *name = (def) ? luaL_optstring(L, narg, def) :
- luaL_checkstring(L, narg);
+ const char *name = (def) ? luaL_optstring(L, arg, def) :
+ luaL_checkstring(L, arg);
int i;
for (i=0; lst[i]; i++)
if (strcmp(lst[i], name) == 0)
return i;
- return luaL_argerror(L, narg,
- lua_pushfstring(L, "invalid option " LUA_QS, name));
+ return luaL_argerror(L, arg,
+ lua_pushfstring(L, "invalid option '%s'", name));
}
@@ -342,77 +361,71 @@ LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) {
}
-LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) {
- if (lua_type(L, narg) != t)
- tag_error(L, narg, t);
+LUALIB_API void luaL_checktype (lua_State *L, int arg, int t) {
+ if (lua_type(L, arg) != t)
+ tag_error(L, arg, t);
}
-LUALIB_API void luaL_checkany (lua_State *L, int narg) {
- if (lua_type(L, narg) == LUA_TNONE)
- luaL_argerror(L, narg, "value expected");
+LUALIB_API void luaL_checkany (lua_State *L, int arg) {
+ if (lua_type(L, arg) == LUA_TNONE)
+ luaL_argerror(L, arg, "value expected");
}
-LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) {
- const char *s = lua_tolstring(L, narg, len);
- if (!s) tag_error(L, narg, LUA_TSTRING);
+LUALIB_API const char *luaL_checklstring (lua_State *L, int arg, size_t *len) {
+ const char *s = lua_tolstring(L, arg, len);
+ if (!s) tag_error(L, arg, LUA_TSTRING);
return s;
}
-LUALIB_API const char *luaL_optlstring (lua_State *L, int narg,
+LUALIB_API const char *luaL_optlstring (lua_State *L, int arg,
const char *def, size_t *len) {
- if (lua_isnoneornil(L, narg)) {
+ if (lua_isnoneornil(L, arg)) {
if (len)
*len = (def ? strlen(def) : 0);
return def;
}
- else return luaL_checklstring(L, narg, len);
+ else return luaL_checklstring(L, arg, len);
}
-LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {
+LUALIB_API lua_Number luaL_checknumber (lua_State *L, int arg) {
int isnum;
- lua_Number d = lua_tonumberx(L, narg, &isnum);
+ lua_Number d = lua_tonumberx(L, arg, &isnum);
if (!isnum)
- tag_error(L, narg, LUA_TNUMBER);
+ tag_error(L, arg, LUA_TNUMBER);
return d;
}
-LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) {
- return luaL_opt(L, luaL_checknumber, narg, def);
+LUALIB_API lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number def) {
+ return luaL_opt(L, luaL_checknumber, arg, def);
}
-LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {
- int isnum;
- lua_Integer d = lua_tointegerx(L, narg, &isnum);
- if (!isnum)
- tag_error(L, narg, LUA_TNUMBER);
- return d;
+static void interror (lua_State *L, int arg) {
+ if (lua_isnumber(L, arg))
+ luaL_argerror(L, arg, "number has no integer representation");
+ else
+ tag_error(L, arg, LUA_TNUMBER);
}
-LUALIB_API lua_Unsigned luaL_checkunsigned (lua_State *L, int narg) {
+LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int arg) {
int isnum;
- lua_Unsigned d = lua_tounsignedx(L, narg, &isnum);
- if (!isnum)
- tag_error(L, narg, LUA_TNUMBER);
+ lua_Integer d = lua_tointegerx(L, arg, &isnum);
+ if (!isnum) {
+ interror(L, arg);
+ }
return d;
}
-LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg,
+LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int arg,
lua_Integer def) {
- return luaL_opt(L, luaL_checkinteger, narg, def);
-}
-
-
-LUALIB_API lua_Unsigned luaL_optunsigned (lua_State *L, int narg,
- lua_Unsigned def) {
- return luaL_opt(L, luaL_checkunsigned, narg, def);
+ return luaL_opt(L, luaL_checkinteger, arg, def);
}
/* }====================================================== */
@@ -424,6 +437,47 @@ LUALIB_API lua_Unsigned luaL_optunsigned (lua_State *L, int narg,
** =======================================================
*/
+/* userdata to box arbitrary data */
+typedef struct UBox {
+ void *box;
+ size_t bsize;
+} UBox;
+
+
+static void *resizebox (lua_State *L, int idx, size_t newsize) {
+ void *ud;
+ lua_Alloc allocf = lua_getallocf(L, &ud);
+ UBox *box = (UBox *)lua_touserdata(L, idx);
+ void *temp = allocf(ud, box->box, box->bsize, newsize);
+ if (temp == NULL && newsize > 0) { /* allocation error? */
+ resizebox(L, idx, 0); /* free buffer */
+ luaL_error(L, "not enough memory for buffer allocation");
+ }
+ box->box = temp;
+ box->bsize = newsize;
+ return temp;
+}
+
+
+static int boxgc (lua_State *L) {
+ resizebox(L, 1, 0);
+ return 0;
+}
+
+
+static void *newbox (lua_State *L, size_t newsize) {
+ UBox *box = (UBox *)lua_newuserdata(L, sizeof(UBox));
+ box->box = NULL;
+ box->bsize = 0;
+ if (luaL_newmetatable(L, "LUABOX")) { /* creating metatable? */
+ lua_pushcfunction(L, boxgc);
+ lua_setfield(L, -2, "__gc"); /* metatable.__gc = boxgc */
+ }
+ lua_setmetatable(L, -2);
+ return resizebox(L, -1, newsize);
+}
+
+
/*
** check whether buffer is using a userdata on the stack as a temporary
** buffer
@@ -444,11 +498,12 @@ LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) {
if (newsize < B->n || newsize - B->n < sz)
luaL_error(L, "buffer too large");
/* create larger buffer */
- newbuff = (char *)lua_newuserdata(L, newsize * sizeof(char));
- /* move content to new buffer */
- memcpy(newbuff, B->b, B->n * sizeof(char));
if (buffonstack(B))
- lua_remove(L, -2); /* remove old buffer */
+ newbuff = (char *)resizebox(L, -1, newsize);
+ else { /* no buffer yet */
+ newbuff = (char *)newbox(L, newsize);
+ memcpy(newbuff, B->b, B->n * sizeof(char)); /* copy original content */
+ }
B->b = newbuff;
B->size = newsize;
}
@@ -457,9 +512,11 @@ LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) {
LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {
- char *b = luaL_prepbuffsize(B, l);
- memcpy(b, s, l * sizeof(char));
- luaL_addsize(B, l);
+ if (l > 0) { /* avoid 'memcpy' when 's' can be NULL */
+ char *b = luaL_prepbuffsize(B, l);
+ memcpy(b, s, l * sizeof(char));
+ luaL_addsize(B, l);
+ }
}
@@ -471,8 +528,10 @@ LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
lua_State *L = B->L;
lua_pushlstring(L, B->b, B->n);
- if (buffonstack(B))
- lua_remove(L, -2); /* remove old buffer */
+ if (buffonstack(B)) {
+ resizebox(L, -2, 0); /* delete old buffer */
+ lua_remove(L, -2); /* remove its header from the stack */
+ }
}
@@ -523,7 +582,7 @@ LUALIB_API int luaL_ref (lua_State *L, int t) {
int ref;
if (lua_isnil(L, -1)) {
lua_pop(L, 1); /* remove from stack */
- return LUA_REFNIL; /* `nil' has a unique fixed reference */
+ return LUA_REFNIL; /* 'nil' has a unique fixed reference */
}
t = lua_absindex(L, t);
lua_rawgeti(L, t, freelist); /* get first free element */
@@ -562,7 +621,7 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
typedef struct LoadF {
int n; /* number of pre-read characters */
FILE *f; /* file being read */
- char buff[LUAL_BUFFERSIZE]; /* area for reading file */
+ char buff[BUFSIZ]; /* area for reading file */
} LoadF;
@@ -594,7 +653,7 @@ static int errfile (lua_State *L, const char *what, int fnameindex) {
static int skipBOM (LoadF *lf) {
- const char *p = "\xEF\xBB\xBF"; /* Utf8 BOM mark */
+ const char *p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */
int c;
lf->n = 0;
do {
@@ -655,7 +714,7 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
readstatus = ferror(lf.f);
if (filename) fclose(lf.f); /* close file (even in case of errors) */
if (readstatus) {
- lua_settop(L, fnameindex); /* ignore results from `lua_load' */
+ lua_settop(L, fnameindex); /* ignore results from 'lua_load' */
return errfile(L, "read", fnameindex);
}
lua_remove(L, fnameindex);
@@ -698,23 +757,23 @@ LUALIB_API int luaL_loadstring (lua_State *L, const char *s) {
LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
if (!lua_getmetatable(L, obj)) /* no metatable? */
- return 0;
- lua_pushstring(L, event);
- lua_rawget(L, -2);
- if (lua_isnil(L, -1)) {
- lua_pop(L, 2); /* remove metatable and metafield */
- return 0;
- }
+ return LUA_TNIL;
else {
- lua_remove(L, -2); /* remove only metatable */
- return 1;
+ int tt;
+ lua_pushstring(L, event);
+ tt = lua_rawget(L, -2);
+ if (tt == LUA_TNIL) /* is metafield nil? */
+ lua_pop(L, 2); /* remove metatable and metafield */
+ else
+ lua_remove(L, -2); /* remove only metatable */
+ return tt; /* return metafield type */
}
}
LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
obj = lua_absindex(L, obj);
- if (!luaL_getmetafield(L, obj, event)) /* no metafield? */
+ if (luaL_getmetafield(L, obj, event) == LUA_TNIL) /* no metafield? */
return 0;
lua_pushvalue(L, obj);
lua_call(L, 1, 1);
@@ -722,13 +781,13 @@ LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
}
-LUALIB_API int luaL_len (lua_State *L, int idx) {
- int l;
+LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) {
+ lua_Integer l;
int isnum;
lua_len(L, idx);
- l = (int)lua_tointegerx(L, -1, &isnum);
+ l = lua_tointegerx(L, -1, &isnum);
if (!isnum)
- luaL_error(L, "object length is not a number");
+ luaL_error(L, "object length is not an integer");
lua_pop(L, 1); /* remove object */
return l;
}
@@ -737,7 +796,13 @@ LUALIB_API int luaL_len (lua_State *L, int idx) {
LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */
switch (lua_type(L, idx)) {
- case LUA_TNUMBER:
+ case LUA_TNUMBER: {
+ if (lua_isinteger(L, idx))
+ lua_pushfstring(L, "%I", lua_tointeger(L, idx));
+ else
+ lua_pushfstring(L, "%f", lua_tonumber(L, idx));
+ break;
+ }
case LUA_TSTRING:
lua_pushvalue(L, idx);
break;
@@ -772,8 +837,7 @@ static const char *luaL_findtable (lua_State *L, int idx,
e = strchr(fname, '.');
if (e == NULL) e = fname + strlen(fname);
lua_pushlstring(L, fname, e - fname);
- lua_rawget(L, -2);
- if (lua_isnil(L, -1)) { /* no such field? */
+ if (lua_rawget(L, -2) == LUA_TNIL) { /* no such field? */
lua_pop(L, 1); /* remove this nil */
lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
lua_pushlstring(L, fname, e - fname);
@@ -810,13 +874,12 @@ static int libsize (const luaL_Reg *l) {
LUALIB_API void luaL_pushmodule (lua_State *L, const char *modname,
int sizehint) {
luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); /* get _LOADED table */
- lua_getfield(L, -1, modname); /* get _LOADED[modname] */
- if (!lua_istable(L, -1)) { /* not found? */
+ if (lua_getfield(L, -1, modname) != LUA_TTABLE) { /* no _LOADED[modname]? */
lua_pop(L, 1); /* remove previous result */
/* try global variable (and create one if it does not exist) */
lua_pushglobaltable(L);
if (luaL_findtable(L, 0, modname, sizehint) != NULL)
- luaL_error(L, "name conflict for module " LUA_QS, modname);
+ luaL_error(L, "name conflict for module '%s'", modname);
lua_pushvalue(L, -1);
lua_setfield(L, -3, modname); /* _LOADED[modname] = new table */
}
@@ -846,7 +909,6 @@ LUALIB_API void luaL_openlib (lua_State *L, const char *libname,
** Returns with only the table at the stack.
*/
LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
- luaL_checkversion(L);
luaL_checkstack(L, nup, "too many upvalues");
for (; l->name != NULL; l++) { /* fill the table with given functions */
int i;
@@ -864,8 +926,8 @@ LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
** into the stack
*/
LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) {
- lua_getfield(L, idx, fname);
- if (lua_istable(L, -1)) return 1; /* table already there */
+ if (lua_getfield(L, idx, fname) == LUA_TTABLE)
+ return 1; /* table already there */
else {
lua_pop(L, 1); /* remove previous result */
idx = lua_absindex(L, idx);
@@ -878,22 +940,26 @@ LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) {
/*
-** stripped-down 'require'. Calls 'openf' to open a module,
-** registers the result in 'package.loaded' table and, if 'glb'
-** is true, also registers the result in the global table.
+** Stripped-down 'require': After checking "loaded" table, calls 'openf'
+** to open a module, registers the result in 'package.loaded' table and,
+** if 'glb' is true, also registers the result in the global table.
** Leaves resulting module on the top.
*/
LUALIB_API void luaL_requiref (lua_State *L, const char *modname,
lua_CFunction openf, int glb) {
- lua_pushcfunction(L, openf);
- lua_pushstring(L, modname); /* argument to open function */
- lua_call(L, 1, 1); /* open module */
luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
- lua_pushvalue(L, -2); /* make copy of module (call result) */
- lua_setfield(L, -2, modname); /* _LOADED[modname] = module */
- lua_pop(L, 1); /* remove _LOADED table */
+ lua_getfield(L, -1, modname); /* _LOADED[modname] */
+ if (!lua_toboolean(L, -1)) { /* package not already loaded? */
+ lua_pop(L, 1); /* remove field */
+ lua_pushcfunction(L, openf);
+ lua_pushstring(L, modname); /* argument to open function */
+ lua_call(L, 1, 1); /* call 'openf' to open module */
+ lua_pushvalue(L, -1); /* make copy of module (call result) */
+ lua_setfield(L, -3, modname); /* _LOADED[modname] = module */
+ }
+ lua_remove(L, -2); /* remove _LOADED table */
if (glb) {
- lua_pushvalue(L, -1); /* copy of 'mod' */
+ lua_pushvalue(L, -1); /* copy of module */
lua_setglobal(L, modname); /* _G[modname] = module */
}
}
@@ -908,7 +974,7 @@ LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,
while ((wild = strstr(s, p)) != NULL) {
luaL_addlstring(&b, s, wild - s); /* push prefix */
luaL_addstring(&b, r); /* push replacement in place of pattern */
- s = wild + l; /* continue after `p' */
+ s = wild + l; /* continue after 'p' */
}
luaL_addstring(&b, s); /* push last suffix */
luaL_pushresult(&b);
@@ -928,8 +994,8 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
static int panic (lua_State *L) {
- luai_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
- lua_tostring(L, -1));
+ lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
+ lua_tostring(L, -1));
return 0; /* return to Lua to abort */
}
@@ -941,19 +1007,14 @@ LUALIB_API lua_State *luaL_newstate (void) {
}
-LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver) {
+LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) {
const lua_Number *v = lua_version(L);
+ if (sz != LUAL_NUMSIZES) /* check numeric types */
+ luaL_error(L, "core and library have incompatible numeric types");
if (v != lua_version(NULL))
luaL_error(L, "multiple Lua VMs detected");
else if (*v != ver)
luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f",
ver, *v);
- /* check conversions number -> integer types */
- lua_pushnumber(L, -(lua_Number)0x1234);
- if (lua_tointeger(L, -1) != -0x1234 ||
- lua_tounsigned(L, -1) != (lua_Unsigned)-0x1234)
- luaL_error(L, "bad conversion number->int;"
- " must recompile Lua with proper settings");
- lua_pop(L, 1);
}