|
@@ -1,5 +1,5 @@
|
|
|
/*
|
|
|
-** $Id: lauxlib.c,v 1.167 2007/05/15 18:46:12 roberto Exp roberto $
|
|
|
+** $Id: lauxlib.c,v 1.168 2007/06/21 13:48:04 roberto Exp roberto $
|
|
|
** Auxiliary functions for building Lua libraries
|
|
|
** See Copyright Notice in lua.h
|
|
|
*/
|
|
@@ -25,13 +25,6 @@
|
|
|
#include "lauxlib.h"
|
|
|
|
|
|
|
|
|
-/* number of prereserved references (for internal use) */
|
|
|
-#define RESERVED_REFS 1 /* only FREELIST_REF is reserved */
|
|
|
-
|
|
|
-#define FREELIST_REF 1 /* free list of references */
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
/* convert a stack index to positive */
|
|
|
#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \
|
|
|
lua_gettop(L) + (i) + 1)
|
|
@@ -43,7 +36,6 @@
|
|
|
** =======================================================
|
|
|
*/
|
|
|
|
|
|
-
|
|
|
LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {
|
|
|
lua_Debug ar;
|
|
|
if (!lua_getstack(L, 0, &ar)) /* no stack frame? */
|
|
@@ -100,18 +92,11 @@ LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
|
|
|
/* }====================================================== */
|
|
|
|
|
|
|
|
|
-LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def,
|
|
|
- const char *const lst[]) {
|
|
|
- const char *name = (def) ? luaL_optstring(L, narg, def) :
|
|
|
- luaL_checkstring(L, narg);
|
|
|
- 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));
|
|
|
-}
|
|
|
-
|
|
|
+/*
|
|
|
+** {======================================================
|
|
|
+** Userdata's metatable manipulation
|
|
|
+** =======================================================
|
|
|
+*/
|
|
|
|
|
|
LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
|
|
|
lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */
|
|
@@ -146,6 +131,27 @@ LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
|
|
|
return p;
|
|
|
}
|
|
|
|
|
|
+/* }====================================================== */
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+** {======================================================
|
|
|
+** Argument check functions
|
|
|
+** =======================================================
|
|
|
+*/
|
|
|
+
|
|
|
+LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def,
|
|
|
+ const char *const lst[]) {
|
|
|
+ const char *name = (def) ? luaL_optstring(L, narg, def) :
|
|
|
+ luaL_checkstring(L, narg);
|
|
|
+ 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));
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) {
|
|
|
if (!lua_checkstack(L, space))
|
|
@@ -209,128 +215,7 @@ LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg,
|
|
|
return luaL_opt(L, luaL_checkinteger, narg, def);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-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;
|
|
|
- }
|
|
|
- else {
|
|
|
- lua_remove(L, -2); /* remove only metatable */
|
|
|
- return 1;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
|
|
|
- obj = abs_index(L, obj);
|
|
|
- if (!luaL_getmetafield(L, obj, event)) /* no metafield? */
|
|
|
- return 0;
|
|
|
- lua_pushvalue(L, obj);
|
|
|
- lua_call(L, 1, 1);
|
|
|
- return 1;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-LUALIB_API const char *luaL_tostring (lua_State *L, int idx) {
|
|
|
- if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */
|
|
|
- switch (lua_type(L, idx)) {
|
|
|
- case LUA_TNUMBER:
|
|
|
- return lua_pushstring(L, lua_tostring(L, idx));
|
|
|
- case LUA_TSTRING:
|
|
|
- lua_pushvalue(L, idx);
|
|
|
- break;
|
|
|
- case LUA_TBOOLEAN:
|
|
|
- return lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false"));
|
|
|
- case LUA_TNIL:
|
|
|
- return lua_pushliteral(L, "nil");
|
|
|
- default:
|
|
|
- return lua_pushfstring(L, "%s: %p", luaL_typename(L, idx),
|
|
|
- lua_topointer(L, idx));
|
|
|
- }
|
|
|
- }
|
|
|
- return lua_tostring(L, -1);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static int libsize (const luaL_Reg *l) {
|
|
|
- int size = 0;
|
|
|
- for (; l->name; l++) size++;
|
|
|
- return size;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-LUALIB_API void luaL_register (lua_State *L, const char *libname,
|
|
|
- const luaL_Reg *l) {
|
|
|
- if (libname) {
|
|
|
- int size = libsize(l);
|
|
|
- /* check whether lib already exists */
|
|
|
- luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", size);
|
|
|
- lua_getfield(L, -1, libname); /* get _LOADED[libname] */
|
|
|
- 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, libname, size) != NULL)
|
|
|
- luaL_error(L, "name conflict for module " LUA_QS, libname);
|
|
|
- lua_pushvalue(L, -1);
|
|
|
- lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */
|
|
|
- }
|
|
|
- lua_remove(L, -2); /* remove _LOADED table */
|
|
|
- }
|
|
|
- for (; l->name; l++) {
|
|
|
- lua_pushcfunction(L, l->func);
|
|
|
- lua_setfield(L, -2, l->name);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,
|
|
|
- const char *r) {
|
|
|
- const char *wild;
|
|
|
- size_t l = strlen(p);
|
|
|
- luaL_Buffer b;
|
|
|
- luaL_buffinit(L, &b);
|
|
|
- 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' */
|
|
|
- }
|
|
|
- luaL_addstring(&b, s); /* push last suffix */
|
|
|
- luaL_pushresult(&b);
|
|
|
- return lua_tostring(L, -1);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-LUALIB_API const char *luaL_findtable (lua_State *L, int idx,
|
|
|
- const char *fname, int szhint) {
|
|
|
- const char *e;
|
|
|
- lua_pushvalue(L, idx);
|
|
|
- do {
|
|
|
- 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? */
|
|
|
- lua_pop(L, 1); /* remove this nil */
|
|
|
- lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
|
|
|
- lua_pushlstring(L, fname, e - fname);
|
|
|
- lua_pushvalue(L, -2);
|
|
|
- lua_settable(L, -4); /* set new table into field */
|
|
|
- }
|
|
|
- else if (!lua_istable(L, -1)) { /* field has a non-table value? */
|
|
|
- lua_pop(L, 2); /* remove table and value */
|
|
|
- return fname; /* return problematic part of the name */
|
|
|
- }
|
|
|
- lua_remove(L, -2); /* remove previous table */
|
|
|
- fname = e + 1;
|
|
|
- } while (*e == '.');
|
|
|
- return NULL;
|
|
|
-}
|
|
|
-
|
|
|
+/* }====================================================== */
|
|
|
|
|
|
|
|
|
/*
|
|
@@ -429,6 +314,18 @@ LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
|
|
|
/* }====================================================== */
|
|
|
|
|
|
|
|
|
+/*
|
|
|
+** {======================================================
|
|
|
+** Reference system
|
|
|
+** =======================================================
|
|
|
+*/
|
|
|
+
|
|
|
+/* number of prereserved references (for internal use) */
|
|
|
+#define RESERVED_REFS 1 /* only FREELIST_REF is reserved */
|
|
|
+
|
|
|
+#define FREELIST_REF 1 /* free list of references */
|
|
|
+
|
|
|
+
|
|
|
LUALIB_API int luaL_ref (lua_State *L, int t) {
|
|
|
int ref;
|
|
|
t = abs_index(L, t);
|
|
@@ -464,6 +361,7 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/* }====================================================== */
|
|
|
|
|
|
|
|
|
/*
|
|
@@ -572,9 +470,130 @@ LUALIB_API int luaL_loadstring (lua_State *L, const char *s) {
|
|
|
return luaL_loadbuffer(L, s, strlen(s), 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;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ lua_remove(L, -2); /* remove only metatable */
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
|
|
|
+ obj = abs_index(L, obj);
|
|
|
+ if (!luaL_getmetafield(L, obj, event)) /* no metafield? */
|
|
|
+ return 0;
|
|
|
+ lua_pushvalue(L, obj);
|
|
|
+ lua_call(L, 1, 1);
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+LUALIB_API const char *luaL_tostring (lua_State *L, int idx) {
|
|
|
+ if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */
|
|
|
+ switch (lua_type(L, idx)) {
|
|
|
+ case LUA_TNUMBER:
|
|
|
+ return lua_pushstring(L, lua_tostring(L, idx));
|
|
|
+ case LUA_TSTRING:
|
|
|
+ lua_pushvalue(L, idx);
|
|
|
+ break;
|
|
|
+ case LUA_TBOOLEAN:
|
|
|
+ return lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false"));
|
|
|
+ case LUA_TNIL:
|
|
|
+ return lua_pushliteral(L, "nil");
|
|
|
+ default:
|
|
|
+ return lua_pushfstring(L, "%s: %p", luaL_typename(L, idx),
|
|
|
+ lua_topointer(L, idx));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return lua_tostring(L, -1);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static int libsize (const luaL_Reg *l) {
|
|
|
+ int size = 0;
|
|
|
+ for (; l->name; l++) size++;
|
|
|
+ return size;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+LUALIB_API void luaL_register (lua_State *L, const char *libname,
|
|
|
+ const luaL_Reg *l) {
|
|
|
+ if (libname) {
|
|
|
+ int size = libsize(l);
|
|
|
+ /* check whether lib already exists */
|
|
|
+ luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", size);
|
|
|
+ lua_getfield(L, -1, libname); /* get _LOADED[libname] */
|
|
|
+ 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, libname, size) != NULL)
|
|
|
+ luaL_error(L, "name conflict for module " LUA_QS, libname);
|
|
|
+ lua_pushvalue(L, -1);
|
|
|
+ lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */
|
|
|
+ }
|
|
|
+ lua_remove(L, -2); /* remove _LOADED table */
|
|
|
+ }
|
|
|
+ for (; l->name; l++) {
|
|
|
+ lua_pushcfunction(L, l->func);
|
|
|
+ lua_setfield(L, -2, l->name);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,
|
|
|
+ const char *r) {
|
|
|
+ const char *wild;
|
|
|
+ size_t l = strlen(p);
|
|
|
+ luaL_Buffer b;
|
|
|
+ luaL_buffinit(L, &b);
|
|
|
+ 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' */
|
|
|
+ }
|
|
|
+ luaL_addstring(&b, s); /* push last suffix */
|
|
|
+ luaL_pushresult(&b);
|
|
|
+ return lua_tostring(L, -1);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+LUALIB_API const char *luaL_findtable (lua_State *L, int idx,
|
|
|
+ const char *fname, int szhint) {
|
|
|
+ const char *e;
|
|
|
+ lua_pushvalue(L, idx);
|
|
|
+ do {
|
|
|
+ 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? */
|
|
|
+ lua_pop(L, 1); /* remove this nil */
|
|
|
+ lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
|
|
|
+ lua_pushlstring(L, fname, e - fname);
|
|
|
+ lua_pushvalue(L, -2);
|
|
|
+ lua_settable(L, -4); /* set new table into field */
|
|
|
+ }
|
|
|
+ else if (!lua_istable(L, -1)) { /* field has a non-table value? */
|
|
|
+ lua_pop(L, 2); /* remove table and value */
|
|
|
+ return fname; /* return problematic part of the name */
|
|
|
+ }
|
|
|
+ lua_remove(L, -2); /* remove previous table */
|
|
|
+ fname = e + 1;
|
|
|
+ } while (*e == '.');
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
|
|
|
|
|
|
static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
|