summaryrefslogtreecommitdiff
path: root/lib/lua/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/lua/src')
-rw-r--r--lib/lua/src/LuaLib/lauxlib.c316
-rw-r--r--lib/lua/src/LuaLib/lbaselib.c436
-rw-r--r--lib/lua/src/LuaLib/ldblib.c324
-rw-r--r--lib/lua/src/LuaLib/liolib.c534
-rw-r--r--lib/lua/src/LuaLib/lmathlib.c105
-rw-r--r--lib/lua/src/LuaLib/loadlib.c765
-rw-r--r--lib/lua/src/LuaLib/lstrlib.c420
-rw-r--r--lib/lua/src/LuaLib/ltablib.c130
-rw-r--r--lib/lua/src/lapi.c648
-rw-r--r--lib/lua/src/lcode.c469
-rw-r--r--lib/lua/src/ldebug.c335
-rw-r--r--lib/lua/src/ldo.c375
-rw-r--r--lib/lua/src/ldump.c164
-rw-r--r--lib/lua/src/lfunc.c107
-rw-r--r--lib/lua/src/lgc.c778
-rw-r--r--lib/lua/src/llex.c559
-rw-r--r--lib/lua/src/lmem.c97
-rw-r--r--lib/lua/src/lobject.c134
-rw-r--r--lib/lua/src/lopcodes.c102
-rw-r--r--lib/lua/src/lparser.c622
-rw-r--r--lib/lua/src/lstate.c207
-rw-r--r--lib/lua/src/lstring.c63
-rw-r--r--lib/lua/src/ltable.c493
-rw-r--r--lib/lua/src/ltm.c29
-rw-r--r--lib/lua/src/luacomp.c45
-rw-r--r--lib/lua/src/lundump.c287
-rw-r--r--lib/lua/src/lvm.c829
-rw-r--r--lib/lua/src/lzio.c37
28 files changed, 5261 insertions, 4149 deletions
diff --git a/lib/lua/src/LuaLib/lauxlib.c b/lib/lua/src/LuaLib/lauxlib.c
index 2088b9e..9df860c 100644
--- a/lib/lua/src/LuaLib/lauxlib.c
+++ b/lib/lua/src/LuaLib/lauxlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lauxlib.c,v 1.4 2004-11-27 21:46:10 pixel Exp $
+** $Id: lauxlib.c,v 1.5 2007-07-27 10:05:55 pixel Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
@@ -9,6 +9,7 @@
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
@@ -17,18 +18,14 @@
*/
#define lauxlib_c
+#define LUA_LIB
#include "lua.h"
#include "lauxlib.h"
-/* number of prereserved references (for internal use) */
-#define RESERVED_REFS 2
-
-/* reserved references */
-#define FREELIST_REF 1 /* free list of references */
-#define ARRAYSIZE_REF 2 /* array sizes */
+#define FREELIST_REF 0 /* free list of references */
/* convert a stack index to positive */
@@ -45,36 +42,38 @@
LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {
lua_Debug ar;
- lua_getstack(L, 0, &ar);
+ if (!lua_getstack(L, 0, &ar)) /* no stack frame? */
+ return luaL_error(L, "bad argument #%d (%s)", narg, 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 `%s' on bad self (%s)", ar.name, extramsg);
+ return luaL_error(L, "calling " LUA_QS " on bad self (%s)",
+ ar.name, extramsg);
}
if (ar.name == NULL)
ar.name = "?";
- return luaL_error(L, "bad argument #%d to `%s' (%s)",
+ return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)",
narg, ar.name, extramsg);
}
LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) {
const char *msg = lua_pushfstring(L, "%s expected, got %s",
- tname, lua_typename(L, lua_type(L,narg)));
+ tname, luaL_typename(L, narg));
return luaL_argerror(L, narg, msg);
}
static void tag_error (lua_State *L, int narg, int tag) {
- luaL_typerror(L, narg, lua_typename(L, tag));
+ luaL_typerror(L, narg, lua_typename(L, tag));
}
LUALIB_API void luaL_where (lua_State *L, int level) {
lua_Debug ar;
if (lua_getstack(L, level, &ar)) { /* check function at level */
- lua_getinfo(L, "Snl", &ar); /* get info about it */
+ lua_getinfo(L, "Sl", &ar); /* get info about it */
if (ar.currentline > 0) { /* is there info? */
lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline);
return;
@@ -97,51 +96,44 @@ LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
/* }====================================================== */
-LUALIB_API int luaL_findstring (const char *name, const char *const list[]) {
+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; list[i]; i++)
- if (strcmp(list[i], name) == 0)
+ for (i=0; lst[i]; i++)
+ if (strcmp(lst[i], name) == 0)
return i;
- return -1; /* name not found */
+ return luaL_argerror(L, narg,
+ lua_pushfstring(L, "invalid option " LUA_QS, name));
}
LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
- lua_pushstring(L, tname);
- lua_rawget(L, LUA_REGISTRYINDEX); /* get registry.name */
+ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */
if (!lua_isnil(L, -1)) /* name already in use? */
return 0; /* leave previous value on top, but return 0 */
lua_pop(L, 1);
lua_newtable(L); /* create metatable */
- lua_pushstring(L, tname);
- lua_pushvalue(L, -2);
- lua_rawset(L, LUA_REGISTRYINDEX); /* registry.name = metatable */
lua_pushvalue(L, -1);
- lua_pushstring(L, tname);
- lua_rawset(L, LUA_REGISTRYINDEX); /* registry[metatable] = name */
+ lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */
return 1;
}
-LUALIB_API void luaL_getmetatable (lua_State *L, const char *tname) {
- lua_pushstring(L, tname);
- lua_rawget(L, LUA_REGISTRYINDEX);
-}
-
-
LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
- const char *tn;
- if (!lua_getmetatable(L, ud)) return NULL; /* no metatable? */
- lua_rawget(L, LUA_REGISTRYINDEX); /* get registry[metatable] */
- tn = lua_tostring(L, -1);
- if (tn && (strcmp(tn, tname) == 0)) {
- lua_pop(L, 1);
- return lua_touserdata(L, ud);
- }
- else {
- lua_pop(L, 1);
- return NULL;
+ void *p = lua_touserdata(L, ud);
+ if (p != NULL) { /* value is a userdata? */
+ if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
+ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
+ if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
+ lua_pop(L, 2); /* remove both metatables */
+ return p;
+ }
+ }
}
+ luaL_typerror(L, ud, tname); /* else error */
+ return NULL; /* to avoid warnings */
}
@@ -164,9 +156,8 @@ LUALIB_API void luaL_checkany (lua_State *L, int narg) {
LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) {
- const char *s = lua_tostring(L, narg);
+ const char *s = lua_tolstring(L, narg, len);
if (!s) tag_error(L, narg, LUA_TSTRING);
- if (len) *len = lua_strlen(L, narg);
return s;
}
@@ -191,8 +182,21 @@ LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {
LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) {
- if (lua_isnoneornil(L, narg)) return def;
- else return luaL_checknumber(L, narg);
+ return luaL_opt(L, luaL_checknumber, narg, def);
+}
+
+
+LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {
+ lua_Integer d = lua_tointeger(L, narg);
+ if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */
+ tag_error(L, narg, LUA_TNUMBER);
+ return d;
+}
+
+
+LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg,
+ lua_Integer def) {
+ return luaL_opt(L, luaL_checkinteger, narg, def);
}
@@ -222,27 +226,43 @@ LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
}
-LUALIB_API void luaL_openlib (lua_State *L, const char *libname,
- const luaL_reg *l, int nup) {
+LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
+ const luaL_Reg *l) {
+ luaI_openlib(L, libname, l, 0);
+}
+
+
+static int libsize (const luaL_Reg *l) {
+ int size = 0;
+ for (; l->name; l++) size++;
+ return size;
+}
+
+
+LUALIB_API void luaI_openlib (lua_State *L, const char *libname,
+ const luaL_Reg *l, int nup) {
if (libname) {
- lua_pushstring(L, libname);
- lua_gettable(L, LUA_GLOBALSINDEX); /* check whether lib already exists */
- if (lua_isnil(L, -1)) { /* no? */
- lua_pop(L, 1);
- lua_newtable(L); /* create it */
- lua_pushstring(L, libname);
- lua_pushvalue(L, -2);
- lua_settable(L, LUA_GLOBALSINDEX); /* register it with given name */
+ 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 */
lua_insert(L, -(nup+1)); /* move library table to below upvalues */
}
for (; l->name; l++) {
int i;
- lua_pushstring(L, l->name);
for (i=0; i<nup; i++) /* copy upvalues to the top */
- lua_pushvalue(L, -(nup+1));
+ lua_pushvalue(L, -nup);
lua_pushcclosure(L, l->func, nup);
- lua_settable(L, -(nup+3));
+ lua_setfield(L, -(nup+2), l->name);
}
lua_pop(L, nup); /* remove upvalues */
}
@@ -255,50 +275,50 @@ LUALIB_API void luaL_openlib (lua_State *L, const char *libname,
** =======================================================
*/
+#if defined(LUA_COMPAT_GETN)
+
static int checkint (lua_State *L, int topop) {
- int n = (int)lua_tonumber(L, -1);
- if (n == 0 && !lua_isnumber(L, -1)) n = -1;
+ int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1;
lua_pop(L, topop);
return n;
}
static void getsizes (lua_State *L) {
- lua_rawgeti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF);
+ lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES");
if (lua_isnil(L, -1)) { /* no `size' table? */
lua_pop(L, 1); /* remove nil */
lua_newtable(L); /* create it */
lua_pushvalue(L, -1); /* `size' will be its own metatable */
lua_setmetatable(L, -2);
- lua_pushliteral(L, "__mode");
- lua_pushliteral(L, "k");
- lua_rawset(L, -3); /* metatable(N).__mode = "k" */
+ lua_pushliteral(L, "kv");
+ lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */
lua_pushvalue(L, -1);
- lua_rawseti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF); /* store in register */
+ lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */
}
}
-void luaL_setn (lua_State *L, int t, int n) {
+LUALIB_API void luaL_setn (lua_State *L, int t, int n) {
t = abs_index(L, t);
lua_pushliteral(L, "n");
lua_rawget(L, t);
if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */
lua_pushliteral(L, "n"); /* use it */
- lua_pushnumber(L, (lua_Number)n);
+ lua_pushinteger(L, n);
lua_rawset(L, t);
}
else { /* use `sizes' */
getsizes(L);
lua_pushvalue(L, t);
- lua_pushnumber(L, (lua_Number)n);
+ lua_pushinteger(L, n);
lua_rawset(L, -3); /* sizes[t] = n */
lua_pop(L, 1); /* remove `sizes' */
}
}
-int luaL_getn (lua_State *L, int t) {
+LUALIB_API int luaL_getn (lua_State *L, int t) {
int n;
t = abs_index(L, t);
lua_pushliteral(L, "n"); /* try t.n */
@@ -308,19 +328,60 @@ int luaL_getn (lua_State *L, int t) {
lua_pushvalue(L, t);
lua_rawget(L, -2);
if ((n = checkint(L, 2)) >= 0) return n;
- for (n = 1; ; n++) { /* else must count elements */
- lua_rawgeti(L, t, n);
- if (lua_isnil(L, -1)) break;
- lua_pop(L, 1);
- }
- lua_pop(L, 1);
- return n - 1;
+ return (int)lua_objlen(L, t);
}
+#endif
+
/* }====================================================== */
+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;
+}
+
+
+
/*
** {======================================================
** Generic Buffer manipulation
@@ -374,7 +435,7 @@ LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) {
LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {
while (l--)
- luaL_putchar(B, *s++);
+ luaL_addchar(B, *s++);
}
@@ -392,9 +453,10 @@ LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
LUALIB_API void luaL_addvalue (luaL_Buffer *B) {
lua_State *L = B->L;
- size_t vl = lua_strlen(L, -1);
+ size_t vl;
+ const char *s = lua_tolstring(L, -1, &vl);
if (vl <= bufffree(B)) { /* fit into buffer? */
- memcpy(B->p, lua_tostring(L, -1), vl); /* put it there */
+ memcpy(B->p, s, vl); /* put it there */
B->p += vl;
lua_pop(L, 1); /* remove from stack */
}
@@ -424,18 +486,15 @@ LUALIB_API int luaL_ref (lua_State *L, int t) {
return LUA_REFNIL; /* `nil' has a unique fixed reference */
}
lua_rawgeti(L, t, FREELIST_REF); /* get first free element */
- ref = (int)lua_tonumber(L, -1); /* ref = t[FREELIST_REF] */
+ ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */
lua_pop(L, 1); /* remove it from stack */
if (ref != 0) { /* any free element? */
lua_rawgeti(L, t, ref); /* remove it from list */
lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */
}
else { /* no free elements */
- ref = luaL_getn(L, t);
- if (ref < RESERVED_REFS)
- ref = RESERVED_REFS; /* skip reserved references */
+ ref = (int)lua_objlen(L, t);
ref++; /* create new reference */
- luaL_setn(L, t, ref);
}
lua_rawseti(L, t, ref);
return ref;
@@ -447,7 +506,7 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
t = abs_index(L, t);
lua_rawgeti(L, t, FREELIST_REF);
lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */
- lua_pushnumber(L, (lua_Number)ref);
+ lua_pushinteger(L, ref);
lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */
}
}
@@ -461,6 +520,7 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
*/
typedef struct LoadF {
+ int extraline;
FILE *f;
char buff[LUAL_BUFFERSIZE];
} LoadF;
@@ -469,15 +529,21 @@ typedef struct LoadF {
static const char *getF (lua_State *L, void *ud, size_t *size) {
LoadF *lf = (LoadF *)ud;
(void)L;
+ if (lf->extraline) {
+ lf->extraline = 0;
+ *size = 1;
+ return "\n";
+ }
if (feof(lf->f)) return NULL;
*size = fread(lf->buff, 1, LUAL_BUFFERSIZE, lf->f);
return (*size > 0) ? lf->buff : NULL;
}
-static int errfile (lua_State *L, int fnameindex) {
+static int errfile (lua_State *L, const char *what, int fnameindex) {
+ const char *serr = strerror(errno);
const char *filename = lua_tostring(L, fnameindex) + 1;
- lua_pushfstring(L, "cannot read %s: %s", filename, strerror(errno));
+ lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
lua_remove(L, fnameindex);
return LUA_ERRFILE;
}
@@ -488,6 +554,7 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
int status, readstatus;
int c;
int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
+ lf.extraline = 0;
if (filename == NULL) {
lua_pushliteral(L, "=stdin");
lf.f = stdin;
@@ -495,20 +562,29 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
else {
lua_pushfstring(L, "@%s", filename);
lf.f = fopen(filename, "r");
+ if (lf.f == NULL) return errfile(L, "open", fnameindex);
+ }
+ c = getc(lf.f);
+ if (c == '#') { /* Unix exec. file? */
+ lf.extraline = 1;
+ while ((c = getc(lf.f)) != EOF && c != '\n') ; /* skip first line */
+ if (c == '\n') c = getc(lf.f);
}
- if (lf.f == NULL) return errfile(L, fnameindex); /* unable to open file */
- c = ungetc(getc(lf.f), lf.f);
- if (!(isspace(c) || isprint(c)) && lf.f != stdin) { /* binary file? */
+ if (c == LUA_SIGNATURE[0] && lf.f != stdin) { /* binary file? */
fclose(lf.f);
lf.f = fopen(filename, "rb"); /* reopen in binary mode */
- if (lf.f == NULL) return errfile(L, fnameindex); /* unable to reopen file */
+ if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
+ /* skip eventual `#!...' */
+ while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ;
+ lf.extraline = 0;
}
+ ungetc(c, lf.f);
status = lua_load(L, getF, &lf, lua_tostring(L, -1));
readstatus = ferror(lf.f);
if (lf.f != stdin) fclose(lf.f); /* close file (even in case of errors) */
if (readstatus) {
lua_settop(L, fnameindex); /* ignore results from `lua_load' */
- return errfile(L, fnameindex);
+ return errfile(L, "read", fnameindex);
}
lua_remove(L, fnameindex);
return status;
@@ -539,53 +615,39 @@ LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
return lua_load(L, getS, &ls, name);
}
-/* }====================================================== */
+LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) {
+ return luaL_loadbuffer(L, s, strlen(s), s);
+}
-/*
-** {======================================================
-** compatibility code
-** =======================================================
-*/
-static void callalert (lua_State *L, int status) {
- if (status != 0) {
- lua_getglobal(L, "_ALERT");
- if (lua_isfunction(L, -1)) {
- lua_insert(L, -2);
- lua_call(L, 1, 0);
- }
- else { /* no _ALERT function; print it on stderr */
- fprintf(stderr, "%s\n", lua_tostring(L, -2));
- lua_pop(L, 2); /* remove error message and _ALERT */
- }
- }
-}
+/* }====================================================== */
-static int aux_do (lua_State *L, int status) {
- if (status == 0) { /* parse OK? */
- status = lua_pcall(L, 0, LUA_MULTRET, 0); /* call main */
+static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
+ (void)ud;
+ (void)osize;
+ if (nsize == 0) {
+ free(ptr);
+ return NULL;
}
- callalert(L, status);
- return status;
+ else
+ return realloc(ptr, nsize);
}
-LUALIB_API int lua_dofile (lua_State *L, const char *filename) {
- return aux_do(L, luaL_loadfile(L, filename));
+static int panic (lua_State *L) {
+ (void)L; /* to avoid warnings */
+ fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n",
+ lua_tostring(L, -1));
+ return 0;
}
-LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t size,
- const char *name) {
- return aux_do(L, luaL_loadbuffer(L, buff, size, name));
+LUALIB_API lua_State *luaL_newstate (void) {
+ lua_State *L = lua_newstate(l_alloc, NULL);
+ if (L) lua_atpanic(L, &panic);
+ return L;
}
-
-LUALIB_API int lua_dostring (lua_State *L, const char *str) {
- return lua_dobuffer(L, str, strlen(str), str);
-}
-
-/* }====================================================== */
diff --git a/lib/lua/src/LuaLib/lbaselib.c b/lib/lua/src/LuaLib/lbaselib.c
index 9a173a4..846f26f 100644
--- a/lib/lua/src/LuaLib/lbaselib.c
+++ b/lib/lua/src/LuaLib/lbaselib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lbaselib.c,v 1.7 2007-07-25 16:54:33 pixel Exp $
+** $Id: lbaselib.c,v 1.8 2007-07-27 10:05:55 pixel Exp $
** Basic library
** See Copyright Notice in lua.h
*/
@@ -12,6 +12,7 @@
#include <string.h>
#define lbaselib_c
+#define LUA_LIB
#include "lua.h"
@@ -38,7 +39,8 @@ static int luaB_print (lua_State *L) {
lua_call(L, 1, 1);
s = lua_tostring(L, -1); /* get result */
if (s == NULL)
- return luaL_error(L, "`tostring' must return a string to `print'");
+ return luaL_error(L, LUA_QL("tostring") " must return a string to "
+ LUA_QL("print"));
if (i>1) fputs("\t", stdout);
fputs(s, stdout);
lua_pop(L, 1); /* pop result */
@@ -78,10 +80,8 @@ static int luaB_tonumber (lua_State *L) {
static int luaB_error (lua_State *L) {
int level = luaL_optint(L, 2, 1);
- luaL_checkany(L, 1);
- if (!lua_isstring(L, 1) || level == 0)
- lua_pushvalue(L, 1); /* propagate error message without changes */
- else { /* add extra information */
+ lua_settop(L, 1);
+ if (lua_isstring(L, 1) && level > 0) { /* add extra information? */
luaL_where(L, level);
lua_pushvalue(L, 1);
lua_concat(L, 2);
@@ -114,11 +114,11 @@ static int luaB_setmetatable (lua_State *L) {
}
-static void getfunc (lua_State *L) {
+static void getfunc (lua_State *L, int opt) {
if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);
else {
lua_Debug ar;
- int level = luaL_optint(L, 1, 1);
+ int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1);
luaL_argcheck(L, level >= 0, 1, "level must be non-negative");
if (lua_getstack(L, level, &ar) == 0)
luaL_argerror(L, 1, "invalid level");
@@ -130,35 +130,31 @@ static void getfunc (lua_State *L) {
}
-static int aux_getfenv (lua_State *L) {
- lua_getfenv(L, -1);
- lua_pushliteral(L, "__fenv");
- lua_rawget(L, -2);
- return !lua_isnil(L, -1);
-}
-
-
static int luaB_getfenv (lua_State *L) {
- getfunc(L);
- if (!aux_getfenv(L)) /* __fenv not defined? */
- lua_pop(L, 1); /* remove it, to return real environment */
+ getfunc(L, 1);
+ if (lua_iscfunction(L, -1)) /* is a C function? */
+ lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */
+ else
+ lua_getfenv(L, -1);
return 1;
}
static int luaB_setfenv (lua_State *L) {
luaL_checktype(L, 2, LUA_TTABLE);
- getfunc(L);
- if (aux_getfenv(L)) /* __fenv defined? */
- luaL_error(L, "`setfenv' cannot change a protected environment");
- else
- lua_pop(L, 2); /* remove __fenv and real environment table */
+ getfunc(L, 0);
lua_pushvalue(L, 2);
- if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0)
- lua_replace(L, LUA_GLOBALSINDEX);
- else if (lua_setfenv(L, -2) == 0)
- luaL_error(L, "`setfenv' cannot change environment of given function");
- return 0;
+ if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {
+ /* change environment of current thread */
+ lua_pushthread(L);
+ lua_insert(L, -2);
+ lua_setfenv(L, -2);
+ return 0;
+ }
+ else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0)
+ luaL_error(L,
+ LUA_QL("setfenv") " cannot change environment of given object");
+ return 1;
}
@@ -189,21 +185,40 @@ static int luaB_rawset (lua_State *L) {
static int luaB_gcinfo (lua_State *L) {
- lua_pushnumber(L, (lua_Number)lua_getgccount(L));
- lua_pushnumber(L, (lua_Number)lua_getgcthreshold(L));
- return 2;
+ lua_pushinteger(L, lua_getgccount(L));
+ return 1;
}
static int luaB_collectgarbage (lua_State *L) {
- lua_setgcthreshold(L, luaL_optint(L, 1, 0));
- return 0;
+ static const char *const opts[] = {"stop", "restart", "collect",
+ "count", "step", "setpause", "setstepmul", NULL};
+ static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
+ LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL};
+ int o = luaL_checkoption(L, 1, "collect", opts);
+ int ex = luaL_optint(L, 2, 0);
+ int res = lua_gc(L, optsnum[o], ex);
+ switch (optsnum[o]) {
+ case LUA_GCCOUNT: {
+ int b = lua_gc(L, LUA_GCCOUNTB, 0);
+ lua_pushnumber(L, res + ((lua_Number)b/1024));
+ return 1;
+ }
+ case LUA_GCSTEP: {
+ lua_pushboolean(L, res);
+ return 1;
+ }
+ default: {
+ lua_pushnumber(L, res);
+ return 1;
+ }
+ }
}
static int luaB_type (lua_State *L) {
luaL_checkany(L, 1);
- lua_pushstring(L, lua_typename(L, lua_type(L, 1)));
+ lua_pushstring(L, luaL_typename(L, 1));
return 1;
}
@@ -222,30 +237,29 @@ static int luaB_next (lua_State *L) {
static int luaB_pairs (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
- lua_pushliteral(L, "next");
- lua_rawget(L, LUA_GLOBALSINDEX); /* return generator, */
+ lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */
lua_pushvalue(L, 1); /* state, */
lua_pushnil(L); /* and initial value */
return 3;
}
+static int ipairsaux (lua_State *L) {
+ int i = luaL_checkint(L, 2);
+ luaL_checktype(L, 1, LUA_TTABLE);
+ i++; /* next value */
+ lua_pushinteger(L, i);
+ lua_rawgeti(L, 1, i);
+ return (lua_isnil(L, -1)) ? 0 : 2;
+}
+
+
static int luaB_ipairs (lua_State *L) {
- lua_Number i = lua_tonumber(L, 2);
luaL_checktype(L, 1, LUA_TTABLE);
- if (i == 0 && lua_isnone(L, 2)) { /* `for' start? */
- lua_pushliteral(L, "ipairs");
- lua_rawget(L, LUA_GLOBALSINDEX); /* return generator, */
- lua_pushvalue(L, 1); /* state, */
- lua_pushnumber(L, 0); /* and initial value */
- return 3;
- }
- else { /* `for' step */
- i++; /* next value */
- lua_pushnumber(L, i);
- lua_rawgeti(L, 1, (int)i);
- return (lua_isnil(L, -1)) ? 0 : 2;
- }
+ lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */
+ lua_pushvalue(L, 1); /* state, */
+ lua_pushinteger(L, 0); /* and initial value */
+ return 3;
}
@@ -274,11 +288,44 @@ 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.
+*/
+static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
+ (void)ud; /* to avoid warnings */
+ luaL_checkstack(L, 2, "too many nested functions");
+ lua_pushvalue(L, 1); /* get function */
+ lua_call(L, 0, 1); /* call it */
+ if (lua_isnil(L, -1)) {
+ *size = 0;
+ return NULL;
+ }
+ else if (lua_isstring(L, -1)) {
+ lua_replace(L, 3); /* save string in a reserved stack slot */
+ return lua_tolstring(L, 3, size);
+ }
+ else luaL_error(L, "reader function must return a string");
+ return NULL; /* to avoid warnings */
+}
+
+
+static int luaB_load (lua_State *L) {
+ int status;
+ const char *cname = 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, NULL, cname);
+ return load_aux(L, status);
+}
+
+
static int luaB_dofile (lua_State *L) {
const char *fname = luaL_optstring(L, 1, NULL);
int n = lua_gettop(L);
- int status = luaL_loadfile(L, fname);
- if (status != 0) lua_error(L);
+ if (luaL_loadfile(L, fname) != 0) lua_error(L);
lua_call(L, 0, LUA_MULTRET);
return lua_gettop(L) - n;
}
@@ -288,22 +335,40 @@ static int luaB_assert (lua_State *L) {
luaL_checkany(L, 1);
if (!lua_toboolean(L, 1))
return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
- lua_settop(L, 1);
- return 1;
+ return lua_gettop(L);
}
static int luaB_unpack (lua_State *L) {
- int n, i;
+ int i, e, n;
luaL_checktype(L, 1, LUA_TTABLE);
- n = luaL_getn(L, 1);
+ i = luaL_optint(L, 2, 1);
+ e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
+ n = e - i + 1; /* number of elements */
+ if (n <= 0) return 0; /* empty range */
luaL_checkstack(L, n, "table too big to unpack");
- for (i=1; i<=n; i++) /* push arg[1...n] */
+ for (; i<=e; i++) /* push arg[i...e] */
lua_rawgeti(L, 1, i);
return n;
}
+static int luaB_select (lua_State *L) {
+ int n = lua_gettop(L);
+ if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
+ lua_pushinteger(L, n-1);
+ return 1;
+ }
+ else {
+ int i = luaL_checkint(L, 1);
+ if (i < 0) i = n + i;
+ else if (i > n) i = n;
+ luaL_argcheck(L, 1 <= i, 1, "index out of range");
+ return n - i;
+ }
+}
+
+
static int luaB_pcall (lua_State *L) {
int status;
luaL_checkany(L, 1);
@@ -327,38 +392,26 @@ static int luaB_xpcall (lua_State *L) {
static int luaB_tostring (lua_State *L) {
- char buff[128];
luaL_checkany(L, 1);
if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */
return 1; /* use its value */
switch (lua_type(L, 1)) {
case LUA_TNUMBER:
lua_pushstring(L, lua_tostring(L, 1));
- return 1;
+ break;
case LUA_TSTRING:
lua_pushvalue(L, 1);
- return 1;
+ break;
case LUA_TBOOLEAN:
lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false"));
- return 1;
- case LUA_TTABLE:
- sprintf(buff, "table: %p", lua_topointer(L, 1));
- break;
- case LUA_TFUNCTION:
- sprintf(buff, "function: %p", lua_topointer(L, 1));
- break;
- case LUA_TUSERDATA:
- case LUA_TLIGHTUSERDATA:
- sprintf(buff, "userdata: %p", lua_touserdata(L, 1));
- break;
- case LUA_TTHREAD:
- sprintf(buff, "thread: %p", (void *)lua_tothread(L, 1));
break;
case LUA_TNIL:
lua_pushliteral(L, "nil");
- return 1;
+ break;
+ default:
+ lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1));
+ break;
}
- lua_pushstring(L, buff);
return 1;
}
@@ -389,150 +442,31 @@ static int luaB_newproxy (lua_State *L) {
}
-/*
-** {======================================================
-** `require' function
-** =======================================================
-*/
-
-
-/* name of global that holds table with loaded packages */
-#define REQTAB "_LOADED"
-
-/* name of global that holds the search path for packages */
-#define LUA_PATH "LUA_PATH"
-
-#ifndef LUA_PATH_SEP
-#define LUA_PATH_SEP ';'
-#endif
-
-#ifndef LUA_PATH_MARK
-#define LUA_PATH_MARK '?'
-#endif
-
-#ifndef LUA_PATH_DEFAULT
-#define LUA_PATH_DEFAULT "?;?.lua"
-#endif
-
-
-static const char *getpath (lua_State *L) {
- const char *path;
- lua_getglobal(L, LUA_PATH); /* try global variable */
- path = lua_tostring(L, -1);
- lua_pop(L, 1);
- if (path) return path;
- path = getenv(LUA_PATH); /* else try environment variable */
- if (path) return path;
- return LUA_PATH_DEFAULT; /* else use default */
-}
-
-
-static const char *pushnextpath (lua_State *L, const char *path) {
- const char *l;
- if (*path == '\0') return NULL; /* no more paths */
- if (*path == LUA_PATH_SEP) path++; /* skip separator */
- l = strchr(path, LUA_PATH_SEP); /* find next separator */
- if (l == NULL) l = path+strlen(path);
- lua_pushlstring(L, path, l - path); /* directory name */
- return l;
-}
-
-
-static void pushcomposename (lua_State *L) {
- const char *path = lua_tostring(L, -1);
- const char *wild;
- int n = 1;
- while ((wild = strchr(path, LUA_PATH_MARK)) != NULL) {
- /* is there stack space for prefix, name, and eventual last sufix? */
- luaL_checkstack(L, 3, "too many marks in a path component");
- lua_pushlstring(L, path, wild - path); /* push prefix */
- lua_pushvalue(L, 1); /* push package name (in place of MARK) */
- path = wild + 1; /* continue after MARK */
- n += 2;
- }
- lua_pushstring(L, path); /* push last sufix (`n' already includes this) */
- lua_concat(L, n);
-}
-
-
-static int luaB_require (lua_State *L) {
- const char *path;
- int status = LUA_ERRFILE; /* not found (yet) */
- luaL_checkstring(L, 1);
- lua_settop(L, 1);
- lua_getglobal(L, REQTAB);
- if (!lua_istable(L, 2)) return luaL_error(L, "`" REQTAB "' is not a table");
- path = getpath(L);
- lua_pushvalue(L, 1); /* check package's name in book-keeping table */
- lua_rawget(L, 2);
- if (lua_toboolean(L, -1)) /* is it there? */
- return 1; /* package is already loaded; return its result */
- else { /* must load it */
- while (status == LUA_ERRFILE) {
- lua_settop(L, 3); /* reset stack position */
- if ((path = pushnextpath(L, path)) == NULL) break;
- pushcomposename(L);
- status = luaL_loadfile(L, lua_tostring(L, -1)); /* try to load it */
- }
- }
- switch (status) {
- case 0: {
- lua_getglobal(L, "_REQUIREDNAME"); /* save previous name */
- lua_insert(L, -2); /* put it below function */
- lua_pushvalue(L, 1);
- lua_setglobal(L, "_REQUIREDNAME"); /* set new name */
- lua_call(L, 0, 1); /* run loaded module */
- lua_insert(L, -2); /* put result below previous name */
- lua_setglobal(L, "_REQUIREDNAME"); /* reset to previous name */
- if (lua_isnil(L, -1)) { /* no/nil return? */
- lua_pushboolean(L, 1);
- lua_replace(L, -2); /* replace to true */
- }
- lua_pushvalue(L, 1);
- lua_pushvalue(L, -2);
- lua_rawset(L, 2); /* mark it as loaded */
- return 1; /* return value */
- }
- case LUA_ERRFILE: { /* file not found */
- return luaL_error(L, "could not load package `%s' from path `%s'",
- lua_tostring(L, 1), getpath(L));
- }
- default: {
- return luaL_error(L, "error loading package `%s' (%s)",
- lua_tostring(L, 1), lua_tostring(L, -1));
- }
- }
-}
-
-/* }====================================================== */
-
-
-static const luaL_reg base_funcs[] = {
+static const luaL_Reg base_funcs[] = {
+ {"assert", luaB_assert},
+ {"collectgarbage", luaB_collectgarbage},
+ {"dofile", luaB_dofile},
{"error", luaB_error},
- {"getmetatable", luaB_getmetatable},
- {"setmetatable", luaB_setmetatable},
+ {"gcinfo", luaB_gcinfo},
{"getfenv", luaB_getfenv},
- {"setfenv", luaB_setfenv},
+ {"getmetatable", luaB_getmetatable},
+ {"loadfile", luaB_loadfile},
+ {"load", luaB_load},
+ {"loadstring", luaB_loadstring},
{"next", luaB_next},
- {"ipairs", luaB_ipairs},
- {"pairs", luaB_pairs},
+ {"pcall", luaB_pcall},
// {"print", luaB_print},
+ {"rawequal", luaB_rawequal},
+ {"rawget", luaB_rawget},
+ {"rawset", luaB_rawset},
+ {"select", luaB_select},
+ {"setfenv", luaB_setfenv},
+ {"setmetatable", luaB_setmetatable},
{"tonumber", luaB_tonumber},
{"tostring", luaB_tostring},
{"type", luaB_type},
- {"assert", luaB_assert},
{"unpack", luaB_unpack},
- {"rawequal", luaB_rawequal},
- {"rawget", luaB_rawget},
- {"rawset", luaB_rawset},
- {"pcall", luaB_pcall},
{"xpcall", luaB_xpcall},
- {"collectgarbage", luaB_collectgarbage},
- {"gcinfo", luaB_gcinfo},
- {"loadfile", luaB_loadfile},
- {"dofile", luaB_dofile},
- {"loadstring", luaB_loadstring},
- {"require", luaB_require},
{NULL, NULL}
};
@@ -547,9 +481,13 @@ static int auxresume (lua_State *L, lua_State *co, int narg) {
int status;
if (!lua_checkstack(co, narg))
luaL_error(L, "too many arguments to resume");
+ if (lua_status(co) == 0 && lua_gettop(co) == 0) {
+ lua_pushliteral(L, "cannot resume dead coroutine");
+ return -1; /* error flag */
+ }
lua_xmove(L, co, narg);
status = lua_resume(co, narg);
- if (status == 0) {
+ if (status == 0 || status == LUA_YIELD) {
int nres = lua_gettop(co);
if (!lua_checkstack(L, nres))
luaL_error(L, "too many results to resume");
@@ -623,55 +561,83 @@ static int luaB_costatus (lua_State *L) {
luaL_argcheck(L, co, 1, "coroutine expected");
if (L == co) lua_pushliteral(L, "running");
else {
- lua_Debug ar;
- if (lua_getstack(co, 0, &ar) == 0 && lua_gettop(co) == 0)
- lua_pushliteral(L, "dead");
- else
- lua_pushliteral(L, "suspended");
+ switch (lua_status(co)) {
+ case LUA_YIELD:
+ lua_pushliteral(L, "suspended");
+ break;
+ case 0: {
+ lua_Debug ar;
+ if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */
+ lua_pushliteral(L, "normal"); /* it is running */
+ else if (lua_gettop(co) == 0)
+ lua_pushliteral(L, "dead");
+ else
+ lua_pushliteral(L, "suspended"); /* initial state */
+ break;
+ }
+ default: /* some error occured */
+ lua_pushliteral(L, "dead");
+ break;
+ }
}
return 1;
}
-static const luaL_reg co_funcs[] = {
+static int luaB_corunning (lua_State *L) {
+ if (lua_pushthread(L))
+ return 0; /* main thread is not a coroutine */
+ else
+ return 1;
+}
+
+
+static const luaL_Reg co_funcs[] = {
{"create", luaB_cocreate},
- {"wrap", luaB_cowrap},
{"resume", luaB_coresume},
- {"yield", luaB_yield},
+ {"running", luaB_corunning},
{"status", luaB_costatus},
+ {"wrap", luaB_cowrap},
+ {"yield", luaB_yield},
{NULL, NULL}
};
/* }====================================================== */
+static void auxopen (lua_State *L, const char *name,
+ lua_CFunction f, lua_CFunction u) {
+ lua_pushcfunction(L, u);
+ lua_pushcclosure(L, f, 1);
+ lua_setfield(L, -2, name);
+}
+
static void base_open (lua_State *L) {
- lua_pushliteral(L, "_G");
+ /* set global _G */
lua_pushvalue(L, LUA_GLOBALSINDEX);
- luaL_openlib(L, NULL, base_funcs, 0); /* open lib into global table */
- lua_pushliteral(L, "_VERSION");
+ lua_setglobal(L, "_G");
+ /* open lib into global table */
+ luaL_register(L, "_G", base_funcs);
lua_pushliteral(L, LUA_VERSION);
- lua_rawset(L, -3); /* set global _VERSION */
+ lua_setglobal(L, "_VERSION"); /* set global _VERSION */
+ /* `ipairs' and `pairs' need auxliliary functions as upvalues */
+ auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
+ auxopen(L, "pairs", luaB_pairs, luaB_next);
/* `newproxy' needs a weaktable as upvalue */
- lua_pushliteral(L, "newproxy");
- lua_newtable(L); /* new table `w' */
+ lua_createtable(L, 0, 1); /* new table `w' */
lua_pushvalue(L, -1); /* `w' will be its own metatable */
lua_setmetatable(L, -2);
- lua_pushliteral(L, "__mode");
- lua_pushliteral(L, "k");
- lua_rawset(L, -3); /* metatable(w).__mode = "k" */
+ lua_pushliteral(L, "kv");
+ lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */
lua_pushcclosure(L, luaB_newproxy, 1);
- lua_rawset(L, -3); /* set global `newproxy' */
- lua_rawset(L, -1); /* set global _G */
+ lua_setglobal(L, "newproxy"); /* set global `newproxy' */
}
LUALIB_API int luaopen_base (lua_State *L) {
base_open(L);
- luaL_openlib(L, LUA_COLIBNAME, co_funcs, 0);
- lua_newtable(L);
- lua_setglobal(L, REQTAB);
- return 0;
+ luaL_register(L, LUA_COLIBNAME, co_funcs);
+ return 2;
}
diff --git a/lib/lua/src/LuaLib/ldblib.c b/lib/lua/src/LuaLib/ldblib.c
index 2449b90..076ddac 100644
--- a/lib/lua/src/LuaLib/ldblib.c
+++ b/lib/lua/src/LuaLib/ldblib.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldblib.c,v 1.4 2004-11-27 21:46:10 pixel Exp $
+** $Id: ldblib.c,v 1.5 2007-07-27 10:05:55 pixel Exp $
** Interface from Lua to its debug API
** See Copyright Notice in lua.h
*/
@@ -10,6 +10,7 @@
#include <string.h>
#define ldblib_c
+#define LUA_LIB
#include "lua.h"
@@ -18,75 +19,137 @@
+static int db_getregistry (lua_State *L) {
+ lua_pushvalue(L, LUA_REGISTRYINDEX);
+ return 1;
+}
+
+
+static int db_getmetatable (lua_State *L) {
+ luaL_checkany(L, 1);
+ if (!lua_getmetatable(L, 1)) {
+ lua_pushnil(L); /* no metatable */
+ }
+ return 1;
+}
+
+
+static int db_setmetatable (lua_State *L) {
+ int t = lua_type(L, 2);
+ luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
+ "nil or table expected");
+ lua_settop(L, 2);
+ lua_pushboolean(L, lua_setmetatable(L, 1));
+ return 1;
+}
+
+
+static int db_getfenv (lua_State *L) {
+ lua_getfenv(L, 1);
+ return 1;
+}
+
+
+static int db_setfenv (lua_State *L) {
+ luaL_checktype(L, 2, LUA_TTABLE);
+ lua_settop(L, 2);
+ if (lua_setfenv(L, 1) == 0)
+ luaL_error(L, LUA_QL("setfenv")
+ " cannot change environment of given object");
+ return 1;
+}
+
+
static void settabss (lua_State *L, const char *i, const char *v) {
- lua_pushstring(L, i);
lua_pushstring(L, v);
- lua_rawset(L, -3);
+ lua_setfield(L, -2, i);
}
static void settabsi (lua_State *L, const char *i, int v) {
- lua_pushstring(L, i);
- lua_pushnumber(L, (lua_Number)v);
- lua_rawset(L, -3);
+ lua_pushinteger(L, v);
+ lua_setfield(L, -2, i);
}
-static int getinfo (lua_State *L) {
+static lua_State *getthread (lua_State *L, int *arg) {
+ if (lua_isthread(L, 1)) {
+ *arg = 1;
+ return lua_tothread(L, 1);
+ }
+ else {
+ *arg = 0;
+ return L;
+ }
+}
+
+
+static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
+ if (L == L1) {
+ lua_pushvalue(L, -2);
+ lua_remove(L, -3);
+ }
+ else
+ lua_xmove(L1, L, 1);
+ lua_setfield(L, -2, fname);
+}
+
+
+static int db_getinfo (lua_State *L) {
lua_Debug ar;
- const char *options = luaL_optstring(L, 2, "flnSu");
- if (lua_isnumber(L, 1)) {
- if (!lua_getstack(L, (int)(lua_tonumber(L, 1)), &ar)) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ const char *options = luaL_optstring(L, arg+2, "flnSu");
+ if (lua_isnumber(L, arg+1)) {
+ if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {
lua_pushnil(L); /* level out of range */
return 1;
}
}
- else if (lua_isfunction(L, 1)) {
+ else if (lua_isfunction(L, arg+1)) {
lua_pushfstring(L, ">%s", options);
options = lua_tostring(L, -1);
- lua_pushvalue(L, 1);
+ lua_pushvalue(L, arg+1);
+ lua_xmove(L, L1, 1);
}
else
- return luaL_argerror(L, 1, "function or level expected");
- if (!lua_getinfo(L, options, &ar))
- return luaL_argerror(L, 2, "invalid option");
- lua_newtable(L);
- for (; *options; options++) {
- switch (*options) {
- case 'S':
- settabss(L, "source", ar.source);
- settabss(L, "short_src", ar.short_src);
- settabsi(L, "linedefined", ar.linedefined);
- settabss(L, "what", ar.what);
- break;
- case 'l':
- settabsi(L, "currentline", ar.currentline);
- break;
- case 'u':
- settabsi(L, "nups", ar.nups);
- break;
- case 'n':
- settabss(L, "name", ar.name);
- settabss(L, "namewhat", ar.namewhat);
- break;
- case 'f':
- lua_pushliteral(L, "func");
- lua_pushvalue(L, -3);
- lua_rawset(L, -3);
- break;
- }
+ return luaL_argerror(L, arg+1, "function or level expected");
+ if (!lua_getinfo(L1, options, &ar))
+ return luaL_argerror(L, arg+2, "invalid option");
+ lua_createtable(L, 0, 2);
+ if (strchr(options, 'S')) {
+ settabss(L, "source", ar.source);
+ settabss(L, "short_src", ar.short_src);
+ settabsi(L, "linedefined", ar.linedefined);
+ settabsi(L, "lastlinedefined", ar.lastlinedefined);
+ settabss(L, "what", ar.what);
+ }
+ if (strchr(options, 'l'))
+ settabsi(L, "currentline", ar.currentline);
+ if (strchr(options, 'u'))
+ settabsi(L, "nups", ar.nups);
+ if (strchr(options, 'n')) {
+ settabss(L, "name", ar.name);
+ settabss(L, "namewhat", ar.namewhat);
}
+ if (strchr(options, 'L'))
+ treatstackoption(L, L1, "activelines");
+ if (strchr(options, 'f'))
+ treatstackoption(L, L1, "func");
return 1; /* return table */
}
-static int getlocal (lua_State *L) {
+static int db_getlocal (lua_State *L) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
lua_Debug ar;
const char *name;
- if (!lua_getstack(L, luaL_checkint(L, 1), &ar)) /* level out of range? */
- return luaL_argerror(L, 1, "level out of range");
- name = lua_getlocal(L, &ar, luaL_checkint(L, 2));
+ if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */
+ return luaL_argerror(L, arg+1, "level out of range");
+ name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2));
if (name) {
+ lua_xmove(L1, L, 1);
lua_pushstring(L, name);
lua_pushvalue(L, -2);
return 2;
@@ -98,12 +161,16 @@ static int getlocal (lua_State *L) {
}
-static int setlocal (lua_State *L) {
+static int db_setlocal (lua_State *L) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
lua_Debug ar;
- if (!lua_getstack(L, luaL_checkint(L, 1), &ar)) /* level out of range? */
- return luaL_argerror(L, 1, "level out of range");
- luaL_checkany(L, 3);
- lua_pushstring(L, lua_setlocal(L, &ar, luaL_checkint(L, 2)));
+ if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */
+ return luaL_argerror(L, arg+1, "level out of range");
+ luaL_checkany(L, arg+3);
+ lua_settop(L, arg+3);
+ lua_xmove(L, L1, 1);
+ lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2)));
return 1;
}
@@ -121,12 +188,12 @@ static int auxupvalue (lua_State *L, int get) {
}
-static int getupvalue (lua_State *L) {
+static int db_getupvalue (lua_State *L) {
return auxupvalue(L, 1);
}
-static int setupvalue (lua_State *L) {
+static int db_setupvalue (lua_State *L) {
luaL_checkany(L, 3);
return auxupvalue(L, 0);
}
@@ -141,16 +208,16 @@ static void hookf (lua_State *L, lua_Debug *ar) {
{"call", "return", "line", "count", "tail return"};
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
lua_rawget(L, LUA_REGISTRYINDEX);
+ lua_pushlightuserdata(L, L);
+ lua_rawget(L, -2);
if (lua_isfunction(L, -1)) {
lua_pushstring(L, hooknames[(int)ar->event]);
if (ar->currentline >= 0)
- lua_pushnumber(L, (lua_Number)ar->currentline);
+ lua_pushinteger(L, ar->currentline);
else lua_pushnil(L);
lua_assert(lua_getinfo(L, "lS", ar));
lua_call(L, 2, 0);
}
- else
- lua_pop(L, 1); /* pop result from gettable */
}
@@ -174,48 +241,75 @@ static char *unmakemask (int mask, char *smask) {
}
-static int sethook (lua_State *L) {
- if (lua_isnoneornil(L, 1)) {
- lua_settop(L, 1);
- lua_sethook(L, NULL, 0, 0); /* turn off hooks */
+static void gethooktable (lua_State *L) {
+ lua_pushlightuserdata(L, (void *)&KEY_HOOK);
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ if (!lua_istable(L, -1)) {
+ lua_pop(L, 1);
+ lua_createtable(L, 0, 1);
+ lua_pushlightuserdata(L, (void *)&KEY_HOOK);
+ lua_pushvalue(L, -2);
+ lua_rawset(L, LUA_REGISTRYINDEX);
+ }
+}
+
+
+static int db_sethook (lua_State *L) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ if (lua_isnoneornil(L, arg+1)) {
+ lua_settop(L, arg+1);
+ lua_sethook(L1, NULL, 0, 0); /* turn off hooks */
}
else {
- const char *smask = luaL_checkstring(L, 2);
- int count = luaL_optint(L, 3, 0);
- luaL_checktype(L, 1, LUA_TFUNCTION);
- lua_sethook(L, hookf, makemask(smask, count), count);
+ const char *smask = luaL_checkstring(L, arg+2);
+ int count = luaL_optint(L, arg+3, 0);
+ luaL_checktype(L, arg+1, LUA_TFUNCTION);
+ lua_sethook(L1, hookf, makemask(smask, count), count);
}
- lua_pushlightuserdata(L, (void *)&KEY_HOOK);
- lua_pushvalue(L, 1);
- lua_rawset(L, LUA_REGISTRYINDEX); /* set new hook */
+ gethooktable(L1);
+ lua_pushlightuserdata(L1, L1);
+ lua_pushvalue(L, arg+1);
+ lua_xmove(L, L1, 1);
+ lua_rawset(L1, -3); /* set new hook */
+ lua_pop(L1, 1); /* remove hook table */
return 0;
}
-static int gethook (lua_State *L) {
+static int db_gethook (lua_State *L) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
char buff[5];
- int mask = lua_gethookmask(L);
- lua_Hook hook = lua_gethook(L);
+ int mask = lua_gethookmask(L1);
+ lua_Hook hook = lua_gethook(L1);
if (hook != NULL && hook != hookf) /* external hook? */
lua_pushliteral(L, "external hook");
else {
- lua_pushlightuserdata(L, (void *)&KEY_HOOK);
- lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */
+ gethooktable(L1);
+ lua_pushlightuserdata(L1, L1);
+ lua_rawget(L1, -2); /* get hook */
+ lua_remove(L1, -2); /* remove hook table */
+ lua_xmove(L1, L, 1);
}
lua_pushstring(L, unmakemask(mask, buff));
- lua_pushnumber(L, (lua_Number)lua_gethookcount(L));
+ lua_pushinteger(L, lua_gethookcount(L1));
return 3;
}
-static int debug (lua_State *L) {
+static int db_debug (lua_State *L) {
for (;;) {
char buffer[250];
fputs("lua_debug> ", stderr);
if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
strcmp(buffer, "cont\n") == 0)
return 0;
- lua_dostring(L, buffer);
+ if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
+ lua_pcall(L, 0, 0, 0)) {
+ fputs(lua_tostring(L, -1), stderr);
+ fputs("\n", stderr);
+ }
lua_settop(L, 0); /* remove eventual returns */
}
}
@@ -224,76 +318,80 @@ static int debug (lua_State *L) {
#define LEVELS1 12 /* size of the first part of the stack */
#define LEVELS2 10 /* size of the second part of the stack */
-static int errorfb (lua_State *L) {
- int level = 1; /* skip level 0 (it's this function) */
+static int db_errorfb (lua_State *L) {
+ int level;
int firstpart = 1; /* still before eventual `...' */
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
lua_Debug ar;
- if (lua_gettop(L) == 0)
+ if (lua_isnumber(L, arg+2)) {
+ level = (int)lua_tointeger(L, arg+2);
+ lua_pop(L, 1);
+ }
+ else
+ level = (L == L1) ? 1 : 0; /* level 0 may be this own function */
+ if (lua_gettop(L) == arg)
lua_pushliteral(L, "");
- else if (!lua_isstring(L, 1)) return 1; /* no string message */
+ else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */
else lua_pushliteral(L, "\n");
lua_pushliteral(L, "stack traceback:");
- while (lua_getstack(L, level++, &ar)) {
+ while (lua_getstack(L1, level++, &ar)) {
if (level > LEVELS1 && firstpart) {
/* no more than `LEVELS2' more levels? */
- if (!lua_getstack(L, level+LEVELS2, &ar))
+ if (!lua_getstack(L1, level+LEVELS2, &ar))
level--; /* keep going */
else {
lua_pushliteral(L, "\n\t..."); /* too many levels */
- while (lua_getstack(L, level+LEVELS2, &ar)) /* find last levels */
+ while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */
level++;
}
firstpart = 0;
continue;
}
lua_pushliteral(L, "\n\t");
- lua_getinfo(L, "Snl", &ar);
+ lua_getinfo(L1, "Snl", &ar);
lua_pushfstring(L, "%s:", ar.short_src);
if (ar.currentline > 0)
lua_pushfstring(L, "%d:", ar.currentline);
- switch (*ar.namewhat) {
- case 'g': /* global */
- case 'l': /* local */
- case 'f': /* field */
- case 'm': /* method */
- lua_pushfstring(L, " in function `%s'", ar.name);
- break;
- default: {
- if (*ar.what == 'm') /* main? */
- lua_pushfstring(L, " in main chunk");
- else if (*ar.what == 'C' || *ar.what == 't')
- lua_pushliteral(L, " ?"); /* C function or tail call */
- else
- lua_pushfstring(L, " in function <%s:%d>",
- ar.short_src, ar.linedefined);
- }
+ if (*ar.namewhat != '\0') /* is there a name? */
+ lua_pushfstring(L, " in function " LUA_QS, ar.name);
+ else {
+ if (*ar.what == 'm') /* main? */
+ lua_pushfstring(L, " in main chunk");
+ else if (*ar.what == 'C' || *ar.what == 't')
+ lua_pushliteral(L, " ?"); /* C function or tail call */
+ else
+ lua_pushfstring(L, " in function <%s:%d>",
+ ar.short_src, ar.linedefined);
}
- lua_concat(L, lua_gettop(L));
+ lua_concat(L, lua_gettop(L) - arg);
}
- lua_concat(L, lua_gettop(L));
+ lua_concat(L, lua_gettop(L) - arg);
return 1;
}
-static const luaL_reg dblib[] = {
- {"getlocal", getlocal},
- {"getinfo", getinfo},
- {"gethook", gethook},
- {"getupvalue", getupvalue},
- {"sethook", sethook},
- {"setlocal", setlocal},
- {"setupvalue", setupvalue},
- {"debug", debug},
- {"traceback", errorfb},
+static const luaL_Reg dblib[] = {
+ {"debug", db_debug},
+ {"getfenv", db_getfenv},
+ {"gethook", db_gethook},
+ {"getinfo", db_getinfo},
+ {"getlocal", db_getlocal},
+ {"getregistry", db_getregistry},
+ {"getmetatable", db_getmetatable},
+ {"getupvalue", db_getupvalue},
+ {"setfenv", db_setfenv},
+ {"sethook", db_sethook},
+ {"setlocal", db_setlocal},
+ {"setmetatable", db_setmetatable},
+ {"setupvalue", db_setupvalue},
+ {"traceback", db_errorfb},
{NULL, NULL}
};
LUALIB_API int luaopen_debug (lua_State *L) {
- luaL_openlib(L, LUA_DBLIBNAME, dblib, 0);
- lua_pushliteral(L, "_TRACEBACK");
- lua_pushcfunction(L, errorfb);
- lua_settable(L, LUA_GLOBALSINDEX);
+ luaL_register(L, LUA_DBLIBNAME, dblib);
return 1;
}
diff --git a/lib/lua/src/LuaLib/liolib.c b/lib/lua/src/LuaLib/liolib.c
index bd3b2ed..f9866c3 100644
--- a/lib/lua/src/LuaLib/liolib.c
+++ b/lib/lua/src/LuaLib/liolib.c
@@ -1,18 +1,17 @@
/*
-** $Id: liolib.c,v 1.6 2007-07-25 16:54:33 pixel Exp $
+** $Id: liolib.c,v 1.7 2007-07-27 10:05:55 pixel Exp $
** Standard I/O (and system) library
** See Copyright Notice in lua.h
*/
#include <errno.h>
-#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <time.h>
#define liolib_c
+#define LUA_LIB
#include "lua.h"
@@ -20,62 +19,16 @@
#include "lualib.h"
-typedef struct FileHandle {
- FILE *f;
- int ispipe;
-} FileHandle;
-
-
-
-/*
-** by default, gcc does not get `tmpname'
-*/
-#ifndef USE_TMPNAME
-#ifdef __GNUC__
-#define USE_TMPNAME 0
-#else
-#define USE_TMPNAME 1
-#endif
-#endif
-
-
-/*
-** by default, posix systems get `popen'
-*/
-#ifndef USE_POPEN
-#ifdef _POSIX_C_SOURCE
-#if _POSIX_C_SOURCE >= 2
-#define USE_POPEN 1
-#endif
-#endif
-#endif
-
-#ifndef USE_POPEN
-#define USE_POPEN 0
-#endif
-
-
-
-
-/*
-** {======================================================
-** FILE Operations
-** =======================================================
-*/
-
-#if !USE_POPEN
-#define pclose(f) (-1)
-#endif
+#define IO_INPUT 1
+#define IO_OUTPUT 2
-#define FILEHANDLE "FILE*"
-
-#define IO_INPUT "_input"
-#define IO_OUTPUT "_output"
+static const char *const fnames[] = {"input", "output"};
static int pushresult (lua_State *L, int i, const char *filename) {
+ int en = errno; /* calls to Lua API may change this value */
if (i) {
lua_pushboolean(L, 1);
return 1;
@@ -83,26 +36,32 @@ static int pushresult (lua_State *L, int i, const char *filename) {
else {
lua_pushnil(L);
if (filename)
- lua_pushfstring(L, "%s: %s", filename, strerror(errno));
+ lua_pushfstring(L, "%s: %s", filename, strerror(en));
else
- lua_pushfstring(L, "%s", strerror(errno));
- lua_pushnumber(L, errno);
+ lua_pushfstring(L, "%s", strerror(en));
+ lua_pushinteger(L, en);
return 3;
}
}
-static FileHandle *topfile (lua_State *L, int findex) {
- FileHandle *fh = (FileHandle *)luaL_checkudata(L, findex, FILEHANDLE);
- if (fh == NULL) luaL_argerror(L, findex, "bad file");
- return fh;
+static void fileerror (lua_State *L, int arg, const char *filename) {
+ lua_pushfstring(L, "%s: %s", filename, strerror(errno));
+ luaL_argerror(L, arg, lua_tostring(L, -1));
}
+#define topfile(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))
+
+
static int io_type (lua_State *L) {
- FileHandle *fh = (FileHandle *)luaL_checkudata(L, 1, FILEHANDLE);
- if (fh == NULL) lua_pushnil(L);
- else if (fh->f == NULL)
+ void *ud;
+ luaL_checkany(L, 1);
+ ud = lua_touserdata(L, 1);
+ lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
+ if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1))
+ lua_pushnil(L); /* not a file */
+ else if (*((FILE **)ud) == NULL)
lua_pushliteral(L, "closed file");
else
lua_pushliteral(L, "file");
@@ -110,89 +69,79 @@ static int io_type (lua_State *L) {
}
-#define tofile(L,i) (tofileh(L,i)->f)
-
-static FileHandle *tofileh (lua_State *L, int findex) {
- FileHandle *fh = topfile(L, findex);
- if (fh->f == NULL)
+static FILE *tofile (lua_State *L) {
+ FILE **f = topfile(L);
+ if (*f == NULL)
luaL_error(L, "attempt to use a closed file");
- return fh;
+ return *f;
}
-#define newfile(L) (&(newfileh(L)->f))
-
/*
** When creating file handles, always creates a `closed' file handle
** before opening the actual file; so, if there is a memory error, the
** file is not left opened.
*/
-static FileHandle *newfileh (lua_State *L) {
- FileHandle *fh = (FileHandle *)lua_newuserdata(L, sizeof(FileHandle));
- fh->f = NULL; /* file handle is currently `closed' */
- fh->ispipe = 0;
- luaL_getmetatable(L, FILEHANDLE);
+static FILE **newfile (lua_State *L) {
+ FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
+ *pf = NULL; /* file handle is currently `closed' */
+ luaL_getmetatable(L, LUA_FILEHANDLE);
lua_setmetatable(L, -2);
- return fh;
+ return pf;
}
/*
-** assumes that top of the stack is the `io' library, and next is
-** the `io' metatable
+** this function has a separated environment, which defines the
+** correct __close for 'popen' files
*/
-static void registerfile (lua_State *L, FILE *f, const char *name,
- const char *impname) {
- lua_pushstring(L, name);
- *newfile(L) = f;
- if (impname) {
- lua_pushstring(L, impname);
- lua_pushvalue(L, -2);
- lua_settable(L, -6); /* metatable[impname] = file */
- }
- lua_settable(L, -3); /* io[name] = file */
+static int io_pclose (lua_State *L) {
+ FILE **p = topfile(L);
+ int ok = lua_pclose(L, *p);
+ *p = NULL;
+ return pushresult(L, ok, NULL);
+}
+
+
+static int io_fclose (lua_State *L) {
+ FILE **p = topfile(L);
+ int ok = (fclose(*p) == 0);
+ *p = NULL;
+ return pushresult(L, ok, NULL);
}
static int aux_close (lua_State *L) {
- FileHandle *fh = tofileh(L, 1);
- FILE *f = fh->f;
- if (f == stdin || f == stdout || f == stderr)
- return 0; /* file cannot be closed */
- else {
- int ok = fh->ispipe ? (pclose(f) != -1) : (fclose(f) == 0);
- fh->f = NULL; /* mark file as closed */
- return ok;
- }
+ lua_getfenv(L, 1);
+ lua_getfield(L, -1, "__close");
+ return (lua_tocfunction(L, -1))(L);
}
static int io_close (lua_State *L) {
- if (lua_isnone(L, 1) && lua_type(L, lua_upvalueindex(1)) == LUA_TTABLE) {
- lua_pushstring(L, IO_OUTPUT);
- lua_rawget(L, lua_upvalueindex(1));
- }
- return pushresult(L, aux_close(L), NULL);
+ if (lua_isnone(L, 1))
+ lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT);
+ tofile(L); /* make sure argument is a file */
+ return aux_close(L);
}
static int io_gc (lua_State *L) {
- FileHandle *fh = topfile(L, 1);
- if (fh->f != NULL) /* ignore closed files */
+ FILE *f = *topfile(L);
+ /* ignore closed files and standard files */
+ if (f != NULL && f != stdin && f != stdout && f != stderr)
aux_close(L);
return 0;
}
static int io_tostring (lua_State *L) {
- char buff[128];
- FileHandle *fh = topfile(L, 1);
- if (fh->f == NULL)
- strcpy(buff, "closed");
+ FILE *f = *topfile(L);
+ if (f == NULL)
+ lua_pushstring(L, "file (closed)");
else
- sprintf(buff, "%p", lua_touserdata(L, 1));
- lua_pushfstring(L, "file (%s)", buff);
+ lua_pushfstring(L, "file (%p)", f);
return 1;
}
@@ -207,17 +156,11 @@ static int io_open (lua_State *L) {
static int io_popen (lua_State *L) {
-#if !USE_POPEN
- luaL_error(L, "`popen' not supported");
- return 0;
-#else
const char *filename = luaL_checkstring(L, 1);
const char *mode = luaL_optstring(L, 2, "r");
- FileHandle *fh = newfileh(L);
- fh->f = popen(filename, mode);
- fh->ispipe = 1;
- return (fh->f == NULL) ? pushresult(L, 0, filename) : 1;
-#endif
+ FILE **pf = newfile(L);
+ *pf = lua_popen(L, filename, mode);
+ return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
}
@@ -228,34 +171,33 @@ static int io_tmpfile (lua_State *L) {
}
-static FILE *getiofile (lua_State *L, const char *name) {
- lua_pushstring(L, name);
- lua_rawget(L, lua_upvalueindex(1));
- return tofile(L, -1);
+static FILE *getiofile (lua_State *L, int findex) {
+ FILE *f;
+ lua_rawgeti(L, LUA_ENVIRONINDEX, findex);
+ f = *(FILE **)lua_touserdata(L, -1);
+ if (f == NULL)
+ luaL_error(L, "standard %s file is closed", fnames[findex - 1]);
+ return f;
}
-static int g_iofile (lua_State *L, const char *name, const char *mode) {
+static int g_iofile (lua_State *L, int f, const char *mode) {
if (!lua_isnoneornil(L, 1)) {
const char *filename = lua_tostring(L, 1);
- lua_pushstring(L, name);
if (filename) {
FILE **pf = newfile(L);
*pf = fopen(filename, mode);
- if (*pf == NULL) {
- lua_pushfstring(L, "%s: %s", filename, strerror(errno));
- luaL_argerror(L, 1, lua_tostring(L, -1));
- }
+ if (*pf == NULL)
+ fileerror(L, 1, filename);
}
else {
- tofile(L, 1); /* check that it's a valid file handle */
+ tofile(L); /* check that it's a valid file handle */
lua_pushvalue(L, 1);
}
- lua_rawset(L, lua_upvalueindex(1));
+ lua_rawseti(L, LUA_ENVIRONINDEX, f);
}
/* return current value */
- lua_pushstring(L, name);
- lua_rawget(L, lua_upvalueindex(1));
+ lua_rawgeti(L, LUA_ENVIRONINDEX, f);
return 1;
}
@@ -273,17 +215,15 @@ static int io_output (lua_State *L) {
static int io_readline (lua_State *L);
-static void aux_lines (lua_State *L, int idx, int close) {
- lua_pushliteral(L, FILEHANDLE);
- lua_rawget(L, LUA_REGISTRYINDEX);
+static void aux_lines (lua_State *L, int idx, int toclose) {
lua_pushvalue(L, idx);
- lua_pushboolean(L, close); /* close/not close file when finished */
- lua_pushcclosure(L, io_readline, 3);
+ lua_pushboolean(L, toclose); /* close/not close file when finished */
+ lua_pushcclosure(L, io_readline, 2);
}
static int f_lines (lua_State *L) {
- tofile(L, 1); /* check that it's a valid file handle */
+ tofile(L); /* check that it's a valid file handle */
aux_lines(L, 1, 0);
return 1;
}
@@ -291,15 +231,16 @@ static int f_lines (lua_State *L) {
static int io_lines (lua_State *L) {
if (lua_isnoneornil(L, 1)) { /* no arguments? */
- lua_pushstring(L, IO_INPUT);
- lua_rawget(L, lua_upvalueindex(1)); /* will iterate over default input */
+ /* will iterate over default input */
+ lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT);
return f_lines(L);
}
else {
const char *filename = luaL_checkstring(L, 1);
FILE **pf = newfile(L);
*pf = fopen(filename, "r");
- luaL_argcheck(L, *pf, 1, strerror(errno));
+ if (*pf == NULL)
+ fileerror(L, 1, filename);
aux_lines(L, lua_gettop(L), 1);
return 1;
}
@@ -342,7 +283,7 @@ static int read_line (lua_State *L, FILE *f) {
return (lua_strlen(L, -1) > 0); /* check whether read something */
}
l = strlen(p);
- if (p[l-1] != '\n')
+ if (l == 0 || p[l-1] != '\n')
luaL_addsize(&b, l);
else {
luaL_addsize(&b, l - 1); /* do not include `eol' */
@@ -375,6 +316,7 @@ static int g_read (lua_State *L, FILE *f, int first) {
int nargs = lua_gettop(L) - 1;
int success;
int n;
+ clearerr(f);
if (nargs == 0) { /* no arguments? */
success = read_line(L, f);
n = first+1; /* to return 1 result */
@@ -384,7 +326,7 @@ static int g_read (lua_State *L, FILE *f, int first) {
success = 1;
for (n = first; nargs-- && success; n++) {
if (lua_type(L, n) == LUA_TNUMBER) {
- size_t l = (size_t)lua_tonumber(L, n);
+ size_t l = (size_t)lua_tointeger(L, n);
success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
}
else {
@@ -401,14 +343,14 @@ static int g_read (lua_State *L, FILE *f, int first) {
read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */
success = 1; /* always success */
break;
- case 'w': /* word */
- return luaL_error(L, "obsolete option `*w' to `read'");
default:
return luaL_argerror(L, n, "invalid format");
}
}
}
}
+ if (ferror(f))
+ return pushresult(L, 0, NULL);
if (!success) {
lua_pop(L, 1); /* remove last result */
lua_pushnil(L); /* push nil instead */
@@ -423,19 +365,23 @@ static int io_read (lua_State *L) {
static int f_read (lua_State *L) {
- return g_read(L, tofile(L, 1), 2);
+ return g_read(L, tofile(L), 2);
}
static int io_readline (lua_State *L) {
- FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(2));
+ FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1));
+ int sucess;
if (f == NULL) /* file is already closed? */
luaL_error(L, "file is already closed");
- if (read_line(L, f)) return 1;
+ sucess = read_line(L, f);
+ if (ferror(f))
+ return luaL_error(L, "%s", strerror(errno));
+ if (sucess) return 1;
else { /* EOF */
- if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */
+ if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */
lua_settop(L, 0);
- lua_pushvalue(L, lua_upvalueindex(2));
+ lua_pushvalue(L, lua_upvalueindex(1));
aux_close(L); /* close it */
}
return 0;
@@ -470,44 +416,55 @@ static int io_write (lua_State *L) {
static int f_write (lua_State *L) {
- return g_write(L, tofile(L, 1), 2);
+ return g_write(L, tofile(L), 2);
}
static int f_seek (lua_State *L) {
static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
static const char *const modenames[] = {"set", "cur", "end", NULL};
- FILE *f = tofile(L, 1);
- int op = luaL_findstring(luaL_optstring(L, 2, "cur"), modenames);
+ FILE *f = tofile(L);
+ int op = luaL_checkoption(L, 2, "cur", modenames);
long offset = luaL_optlong(L, 3, 0);
- luaL_argcheck(L, op != -1, 2, "invalid mode");
op = fseek(f, offset, mode[op]);
if (op)
return pushresult(L, 0, NULL); /* error */
else {
- lua_pushnumber(L, ftell(f));
+ lua_pushinteger(L, ftell(f));
return 1;
}
}
+static int f_setvbuf (lua_State *L) {
+ static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
+ static const char *const modenames[] = {"no", "full", "line", NULL};
+ FILE *f = tofile(L);
+ int op = luaL_checkoption(L, 2, NULL, modenames);
+ lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
+ int res = setvbuf(f, NULL, mode[op], sz);
+ return pushresult(L, res == 0, NULL);
+}
+
+
+
static int io_flush (lua_State *L) {
return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
}
static int f_flush (lua_State *L) {
- return pushresult(L, fflush(tofile(L, 1)) == 0, NULL);
+ return pushresult(L, fflush(tofile(L)) == 0, NULL);
}
-static const luaL_reg iolib[] = {
- {"input", io_input},
- {"output", io_output},
- {"lines", io_lines},
+static const luaL_Reg iolib[] = {
{"close", io_close},
{"flush", io_flush},
+ {"input", io_input},
+ {"lines", io_lines},
{"open", io_open},
+ {"output", io_output},
{"popen", io_popen},
{"read", io_read},
{"tmpfile", io_tmpfile},
@@ -517,13 +474,14 @@ static const luaL_reg iolib[] = {
};
-static const luaL_reg flib[] = {
+static const luaL_Reg flib[] = {
+ {"close", io_close},
{"flush", f_flush},
- {"read", f_read},
{"lines", f_lines},
+ {"read", f_read},
{"seek", f_seek},
+ {"setvbuf", f_setvbuf},
{"write", f_write},
- {"close", io_close},
{"__gc", io_gc},
{"__tostring", io_tostring},
{NULL, NULL}
@@ -531,232 +489,44 @@ static const luaL_reg flib[] = {
static void createmeta (lua_State *L) {
- luaL_newmetatable(L, FILEHANDLE); /* create new metatable for file handles */
- /* file methods */
- lua_pushliteral(L, "__index");
- lua_pushvalue(L, -2); /* push metatable */
- lua_rawset(L, -3); /* metatable.__index = metatable */
- luaL_openlib(L, NULL, flib, 0);
-}
-
-/* }====================================================== */
-
-
-/*
-** {======================================================
-** Other O.S. Operations
-** =======================================================
-*/
-
-static int io_execute (lua_State *L) {
- lua_pushnumber(L, system(luaL_checkstring(L, 1)));
- return 1;
-}
-
-
-static int io_remove (lua_State *L) {
- const char *filename = luaL_checkstring(L, 1);
- return pushresult(L, remove(filename) == 0, filename);
+ luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */
+ lua_pushvalue(L, -1); /* push metatable */
+ lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
+ luaL_register(L, NULL, flib); /* file methods */
}
-static int io_rename (lua_State *L) {
- const char *fromname = luaL_checkstring(L, 1);
- const char *toname = luaL_checkstring(L, 2);
- return pushresult(L, rename(fromname, toname) == 0, fromname);
-}
-
-
-static int io_tmpname (lua_State *L) {
-#if !USE_TMPNAME
- luaL_error(L, "`tmpname' not supported");
- return 0;
-#else
- char buff[L_tmpnam];
- if (tmpnam(buff) != buff)
- return luaL_error(L, "unable to generate a unique filename in `tmpname'");
- lua_pushstring(L, buff);
- return 1;
-#endif
-}
-
-
-static int io_getenv (lua_State *L) {
- lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */
- return 1;
-}
-
-
-static int io_clock (lua_State *L) {
- lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC);
- return 1;
-}
-
-
-/*
-** {======================================================
-** Time/Date operations
-** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,
-** wday=%w+1, yday=%j, isdst=? }
-** =======================================================
-*/
-
-static void setfield (lua_State *L, const char *key, int value) {
- lua_pushstring(L, key);
- lua_pushnumber(L, value);
- lua_rawset(L, -3);
-}
-
-static void setboolfield (lua_State *L, const char *key, int value) {
- lua_pushstring(L, key);
- lua_pushboolean(L, value);
- lua_rawset(L, -3);
-}
-
-static int getboolfield (lua_State *L, const char *key) {
- int res;
- lua_pushstring(L, key);
- lua_gettable(L, -2);
- res = lua_toboolean(L, -1);
- lua_pop(L, 1);
- return res;
-}
-
-
-static int getfield (lua_State *L, const char *key, int d) {
- int res;
- lua_pushstring(L, key);
- lua_gettable(L, -2);
- if (lua_isnumber(L, -1))
- res = (int)(lua_tonumber(L, -1));
- else {
- if (d == -2)
- return luaL_error(L, "field `%s' missing in date table", key);
- res = d;
- }
- lua_pop(L, 1);
- return res;
-}
-
-
-static int io_date (lua_State *L) {
- const char *s = luaL_optstring(L, 1, "%c");
- time_t t = (time_t)(luaL_optnumber(L, 2, -1));
- struct tm *stm;
- if (t == (time_t)(-1)) /* no time given? */
- t = time(NULL); /* use current time */
- if (*s == '!') { /* UTC? */
- stm = gmtime(&t);
- s++; /* skip `!' */
- }
- else
- stm = localtime(&t);
- if (stm == NULL) /* invalid date? */
- lua_pushnil(L);
- else if (strcmp(s, "*t") == 0) {
- lua_newtable(L);
- setfield(L, "sec", stm->tm_sec);
- setfield(L, "min", stm->tm_min);
- setfield(L, "hour", stm->tm_hour);
- setfield(L, "day", stm->tm_mday);
- setfield(L, "month", stm->tm_mon+1);
- setfield(L, "year", stm->tm_year+1900);
- setfield(L, "wday", stm->tm_wday+1);
- setfield(L, "yday", stm->tm_yday+1);
- setboolfield(L, "isdst", stm->tm_isdst);
- }
- else {
- char b[256];
- if (strftime(b, sizeof(b), s, stm))
- lua_pushstring(L, b);
- else
- return luaL_error(L, "`date' format too long");
- }
- return 1;
-}
-
-
-static int io_time (lua_State *L) {
- if (lua_isnoneornil(L, 1)) /* called without args? */
- lua_pushnumber(L, time(NULL)); /* return current time */
- else {
- time_t t;
- struct tm ts;
- luaL_checktype(L, 1, LUA_TTABLE);
- lua_settop(L, 1); /* make sure table is at the top */
- ts.tm_sec = getfield(L, "sec", 0);
- ts.tm_min = getfield(L, "min", 0);
- ts.tm_hour = getfield(L, "hour", 12);
- ts.tm_mday = getfield(L, "day", -2);
- ts.tm_mon = getfield(L, "month", -2) - 1;
- ts.tm_year = getfield(L, "year", -2) - 1900;
- ts.tm_isdst = getboolfield(L, "isdst");
- t = mktime(&ts);
- if (t == (time_t)(-1))
- lua_pushnil(L);
- else
- lua_pushnumber(L, t);
+static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {
+ *newfile(L) = f;
+ if (k > 0) {
+ lua_pushvalue(L, -1);
+ lua_rawseti(L, LUA_ENVIRONINDEX, k);
}
- return 1;
+ lua_setfield(L, -2, fname);
}
-static int io_difftime (lua_State *L) {
- lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
- (time_t)(luaL_optnumber(L, 2, 0))));
- return 1;
-}
-
-/* }====================================================== */
-
-
-static int io_setloc (lua_State *L) {
- static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,
- LC_NUMERIC, LC_TIME};
- static const char *const catnames[] = {"all", "collate", "ctype", "monetary",
- "numeric", "time", NULL};
- const char *l = lua_tostring(L, 1);
- int op = luaL_findstring(luaL_optstring(L, 2, "all"), catnames);
- luaL_argcheck(L, l || lua_isnoneornil(L, 1), 1, "string expected");
- luaL_argcheck(L, op != -1, 2, "invalid option");
- lua_pushstring(L, setlocale(cat[op], l));
- return 1;
-}
-
-
-static int io_exit (lua_State *L) {
- exit(luaL_optint(L, 1, EXIT_SUCCESS));
- return 0; /* to avoid warnings */
-}
-
-static const luaL_reg syslib[] = {
- {"clock", io_clock},
- {"date", io_date},
- {"difftime", io_difftime},
- {"execute", io_execute},
- {"exit", io_exit},
- {"getenv", io_getenv},
- {"remove", io_remove},
- {"rename", io_rename},
- {"setlocale", io_setloc},
- {"time", io_time},
- {"tmpname", io_tmpname},
- {NULL, NULL}
-};
-
-/* }====================================================== */
-
-
-
LUALIB_API int luaopen_io (lua_State *L) {
- luaL_openlib(L, LUA_OSLIBNAME, syslib, 0);
createmeta(L);
- lua_pushvalue(L, -1);
- luaL_openlib(L, LUA_IOLIBNAME, iolib, 1);
- /* put predefined file handles into `io' table */
- registerfile(L, stdin, "stdin", IO_INPUT);
- registerfile(L, stdout, "stdout", IO_OUTPUT);
- registerfile(L, stderr, "stderr", NULL);
+ /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */
+ lua_createtable(L, 2, 1);
+ lua_replace(L, LUA_ENVIRONINDEX);
+ /* open library */
+ luaL_register(L, LUA_IOLIBNAME, iolib);
+ /* create (and set) default files */
+ createstdfile(L, stdin, IO_INPUT, "stdin");
+ createstdfile(L, stdout, IO_OUTPUT, "stdout");
+ createstdfile(L, stderr, 0, "stderr");
+ /* create environment for 'popen' */
+ lua_getfield(L, -1, "popen");
+ lua_createtable(L, 0, 1);
+ lua_pushcfunction(L, io_pclose);
+ lua_setfield(L, -2, "__close");
+ lua_setfenv(L, -2);
+ lua_pop(L, 1); /* pop 'popen' */
+ /* set default close function */
+ lua_pushcfunction(L, io_fclose);
+ lua_setfield(L, LUA_ENVIRONINDEX, "__close");
return 1;
}
diff --git a/lib/lua/src/LuaLib/lmathlib.c b/lib/lua/src/LuaLib/lmathlib.c
index 998c46c..417fdca 100644
--- a/lib/lua/src/LuaLib/lmathlib.c
+++ b/lib/lua/src/LuaLib/lmathlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lmathlib.c,v 1.4 2004-11-27 21:46:10 pixel Exp $
+** $Id: lmathlib.c,v 1.5 2007-07-27 10:05:55 pixel Exp $
** Standard mathematical library
** See Copyright Notice in lua.h
*/
@@ -9,6 +9,7 @@
#include <math.h>
#define lmathlib_c
+#define LUA_LIB
#include "lua.h"
@@ -22,56 +23,58 @@
-/*
-** If you want Lua to operate in degrees (instead of radians),
-** define USE_DEGREES
-*/
-#ifdef USE_DEGREES
-#define FROMRAD(a) ((a)/RADIANS_PER_DEGREE)
-#define TORAD(a) ((a)*RADIANS_PER_DEGREE)
-#else
-#define FROMRAD(a) (a)
-#define TORAD(a) (a)
-#endif
-
-
static int math_abs (lua_State *L) {
lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));
return 1;
}
static int math_sin (lua_State *L) {
- lua_pushnumber(L, sin(TORAD(luaL_checknumber(L, 1))));
+ lua_pushnumber(L, sin(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_sinh (lua_State *L) {
+ lua_pushnumber(L, sinh(luaL_checknumber(L, 1)));
return 1;
}
static int math_cos (lua_State *L) {
- lua_pushnumber(L, cos(TORAD(luaL_checknumber(L, 1))));
+ lua_pushnumber(L, cos(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_cosh (lua_State *L) {
+ lua_pushnumber(L, cosh(luaL_checknumber(L, 1)));
return 1;
}
static int math_tan (lua_State *L) {
- lua_pushnumber(L, tan(TORAD(luaL_checknumber(L, 1))));
+ lua_pushnumber(L, tan(luaL_checknumber(L, 1)));
+ return 1;
+}
+
+static int math_tanh (lua_State *L) {
+ lua_pushnumber(L, tanh(luaL_checknumber(L, 1)));
return 1;
}
static int math_asin (lua_State *L) {
- lua_pushnumber(L, FROMRAD(asin(luaL_checknumber(L, 1))));
+ lua_pushnumber(L, asin(luaL_checknumber(L, 1)));
return 1;
}
static int math_acos (lua_State *L) {
- lua_pushnumber(L, FROMRAD(acos(luaL_checknumber(L, 1))));
+ lua_pushnumber(L, acos(luaL_checknumber(L, 1)));
return 1;
}
static int math_atan (lua_State *L) {
- lua_pushnumber(L, FROMRAD(atan(luaL_checknumber(L, 1))));
+ lua_pushnumber(L, atan(luaL_checknumber(L, 1)));
return 1;
}
static int math_atan2 (lua_State *L) {
- lua_pushnumber(L, FROMRAD(atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))));
+ lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
return 1;
}
@@ -85,11 +88,19 @@ static int math_floor (lua_State *L) {
return 1;
}
-static int math_mod (lua_State *L) {
+static int math_fmod (lua_State *L) {
lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
return 1;
}
+static int math_modf (lua_State *L) {
+ double ip;
+ double fp = modf(luaL_checknumber(L, 1), &ip);
+ lua_pushnumber(L, ip);
+ lua_pushnumber(L, fp);
+ return 2;
+}
+
static int math_sqrt (lua_State *L) {
lua_pushnumber(L, sqrt(luaL_checknumber(L, 1)));
return 1;
@@ -128,7 +139,7 @@ static int math_rad (lua_State *L) {
static int math_frexp (lua_State *L) {
int e;
lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e));
- lua_pushnumber(L, e);
+ lua_pushinteger(L, e);
return 2;
}
@@ -179,14 +190,14 @@ static int math_random (lua_State *L) {
case 1: { /* only upper limit */
int u = luaL_checkint(L, 1);
luaL_argcheck(L, 1<=u, 1, "interval is empty");
- lua_pushnumber(L, (int)floor(r*u)+1); /* int between 1 and `u' */
+ lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */
break;
}
case 2: { /* lower and upper limits */
int l = luaL_checkint(L, 1);
int u = luaL_checkint(L, 2);
luaL_argcheck(L, l<=u, 2, "interval is empty");
- lua_pushnumber(L, (int)floor(r*(u-l+1))+l); /* int between `l' and `u' */
+ lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */
break;
}
default: return luaL_error(L, "wrong number of arguments");
@@ -201,31 +212,35 @@ static int math_randomseed (lua_State *L) {
}
-static const luaL_reg mathlib[] = {
+static const luaL_Reg mathlib[] = {
{"abs", math_abs},
- {"sin", math_sin},
- {"cos", math_cos},
- {"tan", math_tan},
- {"asin", math_asin},
{"acos", math_acos},
- {"atan", math_atan},
+ {"asin", math_asin},
{"atan2", math_atan2},
+ {"atan", math_atan},
{"ceil", math_ceil},
+ {"cosh", math_cosh},
+ {"cos", math_cos},
+ {"deg", math_deg},
+ {"exp", math_exp},
{"floor", math_floor},
- {"mod", math_mod},
+ {"fmod", math_fmod},
{"frexp", math_frexp},
{"ldexp", math_ldexp},
- {"sqrt", math_sqrt},
- {"min", math_min},
- {"max", math_max},
- {"log", math_log},
{"log10", math_log10},
- {"exp", math_exp},
- {"deg", math_deg},
+ {"log", math_log},
+ {"max", math_max},
+ {"min", math_min},
+ {"modf", math_modf},
{"pow", math_pow},
{"rad", math_rad},
{"random", math_random},
{"randomseed", math_randomseed},
+ {"sinh", math_sinh},
+ {"sin", math_sin},
+ {"sqrt", math_sqrt},
+ {"tanh", math_tanh},
+ {"tan", math_tan},
{NULL, NULL}
};
@@ -234,13 +249,15 @@ static const luaL_reg mathlib[] = {
** Open math library
*/
LUALIB_API int luaopen_math (lua_State *L) {
- luaL_openlib(L, LUA_MATHLIBNAME, mathlib, 0);
- lua_pushliteral(L, "pi");
+ luaL_register(L, LUA_MATHLIBNAME, mathlib);
lua_pushnumber(L, PI);
- lua_settable(L, -3);
- lua_pushliteral(L, "__pow");
- lua_pushcfunction(L, math_pow);
- lua_settable(L, LUA_GLOBALSINDEX);
+ lua_setfield(L, -2, "pi");
+ lua_pushnumber(L, HUGE_VAL);
+ lua_setfield(L, -2, "huge");
+#if defined(LUA_COMPAT_MOD)
+ lua_getfield(L, -1, "fmod");
+ lua_setfield(L, -2, "mod");
+#endif
return 1;
}
diff --git a/lib/lua/src/LuaLib/loadlib.c b/lib/lua/src/LuaLib/loadlib.c
index 8756205..5c6019f 100644
--- a/lib/lua/src/LuaLib/loadlib.c
+++ b/lib/lua/src/LuaLib/loadlib.c
@@ -1,205 +1,664 @@
/*
-** $Id: loadlib.c,v 1.4 2004-11-27 21:46:10 pixel Exp $
+** $Id: loadlib.c,v 1.5 2007-07-27 10:05:55 pixel Exp $
** Dynamic library loader for Lua
** See Copyright Notice in lua.h
-*
-* This Lua library exports a single function, called loadlib, which is
-* called from Lua as loadlib(lib,init), where lib is the full name of the
-* library to be loaded (including the complete path) and init is the name
-* of a function to be called after the library is loaded. Typically, this
-* function will register other functions, thus making the complete library
-* available to Lua. The init function is *not* automatically called by
-* loadlib. Instead, loadlib returns the init function as a Lua function
-* that the client can call when it thinks is appropriate. In the case of
-* errors, loadlib returns nil and two strings describing the error.
-* The first string is supplied by the operating system; it should be
-* informative and useful for error messages. The second string is "open",
-* "init", or "absent" to identify the error and is meant to be used for
-* making decisions without having to look into the first string (whose
-* format is system-dependent).
-*
-* This module contains an implementation of loadlib for Unix systems that
-* have dlfcn, an implementation for Windows, and a stub for other systems.
-* See the list at the end of this file for some links to available
-* implementations of dlfcn and interfaces to other native dynamic loaders
-* on top of which loadlib could be implemented.
-*
+**
+** 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.
*/
+
+#include <stdlib.h>
+#include <string.h>
+
+
+#define loadlib_c
+#define LUA_LIB
+
#include "lua.h"
+
#include "lauxlib.h"
#include "lualib.h"
-#undef LOADLIB
+/* prefix for open functions in C libraries */
+#define LUA_POF "luaopen_"
+
+/* separator for open functions in C libraries */
+#define LUA_OFSEP "_"
+
+
+#define LIBPREFIX "LOADLIB: "
+
+#define POF LUA_POF
+#define LIB_FAIL "open"
+
+
+/* error codes for ll_loadfunc */
+#define ERRLIB 1
+#define ERRFUNC 2
+#define setprogdir(L) ((void)0)
-#ifdef USE_DLOPEN
-#define LOADLIB
+
+static void ll_unloadlib (void *lib);
+static void *ll_load (lua_State *L, const char *path);
+static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym);
+
+
+
+#if defined(LUA_DL_DLOPEN)
/*
-* This is an implementation of loadlib based on the dlfcn interface.
-* The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
-* NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least
-* as an emulation layer on top of native functions.
+** {========================================================================
+** This is an implementation of loadlib based on the dlfcn interface.
+** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
+** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least
+** as an emulation layer on top of native functions.
+** =========================================================================
*/
#include <dlfcn.h>
-static int loadlib(lua_State *L)
-{
- const char *path=luaL_checkstring(L,1);
- const char *init=luaL_checkstring(L,2);
- void *lib=dlopen(path,RTLD_NOW);
- if (lib!=NULL)
- {
- lua_CFunction f=(lua_CFunction) dlsym(lib,init);
- if (f!=NULL)
- {
- lua_pushlightuserdata(L,lib);
- lua_pushcclosure(L,f,1);
- return 1;
- }
- }
- /* else return appropriate error messages */
- lua_pushnil(L);
- lua_pushstring(L,dlerror());
- lua_pushstring(L,(lib!=NULL) ? "init" : "open");
- if (lib!=NULL) dlclose(lib);
- return 3;
+static void ll_unloadlib (void *lib) {
+ dlclose(lib);
}
-#endif
+
+static void *ll_load (lua_State *L, const char *path) {
+ void *lib = dlopen(path, RTLD_NOW);
+ if (lib == NULL) lua_pushstring(L, dlerror());
+ return lib;
+}
+
+
+static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
+ lua_CFunction f = (lua_CFunction)dlsym(lib, sym);
+ if (f == NULL) lua_pushstring(L, dlerror());
+ return f;
+}
+
+/* }====================================================== */
+
+
+
+#elif defined(LUA_DL_DLL)
+/*
+** {======================================================================
+** This is an implementation of loadlib for Windows using native functions.
+** =======================================================================
+*/
+
+#include <windows.h>
+
+
+#undef setprogdir
+
+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)
+ luaL_error(L, "unable to get ModuleFileName");
+ else {
+ *lb = '\0';
+ luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff);
+ lua_remove(L, -2); /* remove original string */
+ }
+}
+
+
+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))
+ lua_pushstring(L, buffer);
+ else
+ lua_pushfstring(L, "system error %d\n", error);
+}
+
+static void ll_unloadlib (void *lib) {
+ FreeLibrary((HINSTANCE)lib);
+}
+
+
+static void *ll_load (lua_State *L, const char *path) {
+ HINSTANCE lib = LoadLibraryA(path);
+ 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((HINSTANCE)lib, sym);
+ if (f == NULL) pusherror(L);
+ return f;
+}
+
+/* }====================================================== */
+#elif defined(LUA_DL_DYLD)
/*
-** In Windows, default is to use dll; otherwise, default is not to use dll
+** {======================================================================
+** Native Mac OS X / Darwin Implementation
+** =======================================================================
*/
-#ifndef USE_DLL
-#ifdef _WIN32
-#define USE_DLL 1
+
+#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
-#define USE_DLL 0
-#endif
+/*
+** {======================================================
+** Fallback for other systems
+** =======================================================
+*/
+
+#undef LIB_FAIL
+#define LIB_FAIL "absent"
+
+
+#define DLMSG "dynamic libraries not enabled; check your Lua installation"
+
+
+static void ll_unloadlib (void *lib) {
+ (void)lib; /* to avoid warnings */
+}
+
+
+static void *ll_load (lua_State *L, const char *path) {
+ (void)path; /* to avoid warnings */
+ 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 */
+ lua_pushliteral(L, DLMSG);
+ return NULL;
+}
+
+/* }====================================================== */
#endif
-#if USE_DLL
-#define LOADLIB
+
+static void **ll_register (lua_State *L, const char *path) {
+ void **plib;
+ lua_pushfstring(L, "%s%s", LIBPREFIX, path);
+ lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */
+ 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);
+ plib = (void **)lua_newuserdata(L, sizeof(const void *));
+ *plib = NULL;
+ luaL_getmetatable(L, "_LOADLIB");
+ lua_setmetatable(L, -2);
+ lua_pushfstring(L, "%s%s", LIBPREFIX, path);
+ lua_pushvalue(L, -2);
+ lua_settable(L, LUA_REGISTRYINDEX);
+ }
+ return plib;
+}
+
+
/*
-* This is an implementation of loadlib for Windows using native functions.
+** __gc tag method: calls library's `ll_unloadlib' function with the lib
+** handle
*/
+static int gctm (lua_State *L) {
+ void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB");
+ if (*lib) ll_unloadlib(*lib);
+ *lib = NULL; /* mark library as closed */
+ return 0;
+}
-#include <windows.h>
-static void pusherror(lua_State *L)
-{
- int error=GetLastError();
- char buffer[128];
- if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
- 0, error, 0, buffer, sizeof(buffer), 0))
- lua_pushstring(L,buffer);
- else
- lua_pushfstring(L,"system error %d\n",error);
-}
-
-static int loadlib(lua_State *L)
-{
- const char *path=luaL_checkstring(L,1);
- const char *init=luaL_checkstring(L,2);
- HINSTANCE lib=LoadLibrary(path);
- if (lib!=NULL)
- {
- lua_CFunction f=(lua_CFunction) GetProcAddress(lib,init);
- if (f!=NULL)
- {
- lua_pushlightuserdata(L,lib);
- lua_pushcclosure(L,f,1);
- return 1;
- }
- }
- lua_pushnil(L);
- pusherror(L);
- lua_pushstring(L,(lib!=NULL) ? "init" : "open");
- if (lib!=NULL) FreeLibrary(lib);
- return 3;
+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 */
+ 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 */
+ }
}
-#endif
+static int ll_loadlib (lua_State *L) {
+ const char *path = luaL_checkstring(L, 1);
+ const char *init = luaL_checkstring(L, 2);
+ int stat = ll_loadfunc(L, path, init);
+ if (stat == 0) /* no errors? */
+ return 1; /* return the loaded function */
+ else { /* error; error message is on stack top */
+ lua_pushnil(L);
+ lua_insert(L, -2);
+ lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init");
+ return 3; /* return nil, error message, and where */
+ }
+}
-#ifndef LOADLIB
-/* Fallback for other systems */
/*
-** Those systems support dlopen, so they should have defined USE_DLOPEN.
-** The default (no)implementation gives them a special error message.
+** {======================================================
+** 'require' function
+** =======================================================
*/
-#ifdef linux
-#define LOADLIB
-#endif
-#ifdef sun
-#define LOADLIB
-#endif
-#ifdef sgi
-#define LOADLIB
-#endif
+static int readable (const char *filename) {
+ FILE *f = fopen(filename, "r"); /* try to open file */
+ if (f == NULL) return 0; /* open failed */
+ fclose(f);
+ return 1;
+}
-#ifdef BSD
-#define LOADLIB
-#endif
-#ifdef _WIN32
-#define LOADLIB
-#endif
+static const char *pushnexttemplate (lua_State *L, const char *path) {
+ const char *l;
+ while (*path == *LUA_PATHSEP) path++; /* skip separators */
+ if (*path == '\0') return NULL; /* no more templates */
+ l = strchr(path, *LUA_PATHSEP); /* find next separator */
+ if (l == NULL) l = path + strlen(path);
+ lua_pushlstring(L, path, l - path); /* template */
+ return l;
+}
-#ifdef LOADLIB
-#undef LOADLIB
-#define LOADLIB "`loadlib' not installed (check your Lua configuration)"
-#else
-#define LOADLIB "`loadlib' not supported"
-#endif
-static int loadlib(lua_State *L)
-{
- lua_pushnil(L);
- lua_pushliteral(L,LOADLIB);
- lua_pushliteral(L,"absent");
- return 3;
+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 */
+ while ((path = pushnexttemplate(L, path)) != NULL) {
+ const char *filename;
+ 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\tno file " LUA_QS, filename);
+ lua_remove(L, -2); /* remove file name */
+ lua_concat(L, 2); /* add entry to possible error message */
+ }
+ return NULL; /* not found */
}
-#endif
-LUALIB_API int luaopen_loadlib (lua_State *L)
-{
- lua_register(L,"loadlib",loadlib);
- return 0;
+
+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 loader_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 */
+}
+
+
+static const char *mkfuncname (lua_State *L, 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;
+}
+
+
+static int loader_C (lua_State *L) {
+ const char *funcname;
+ 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 */
+}
+
+
+static int loader_Croot (lua_State *L) {
+ const char *funcname;
+ 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");
+ 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\tno module " LUA_QS " in file " LUA_QS,
+ name, filename);
+ return 1; /* function not found */
+ }
+ return 1;
+}
+
+
+static int loader_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, -1, name);
+ if (lua_isnil(L, -1)) /* not found? */
+ lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
+ return 1;
+}
+
+
+static const int sentinel_ = 0;
+#define sentinel ((void *)&sentinel_)
+
+
+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);
+ 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 */
+ 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? */
+ 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 */
+ }
+ return 1;
}
+/* }====================================================== */
+
+
+
/*
-* Here are some links to available implementations of dlfcn and
-* interfaces to other native dynamic loaders on top of which loadlib
-* could be implemented. Please send contributions and corrections to us.
-*
-* AIX
-* Starting with AIX 4.2, dlfcn is included in the base OS.
-* There is also an emulation package available.
-* http://www.faqs.org/faqs/aix-faq/part4/section-21.html
-*
-* HPUX
-* HPUX 11 has dlfcn. For HPUX 10 use shl_*.
-* http://www.geda.seul.org/mailinglist/geda-dev37/msg00094.html
-* http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html
-*
-* Macintosh, Windows
-* http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html
-*
-* Mac OS X/Darwin
-* http://www.opendarwin.org/projects/dlcompat/
-*
-* GLIB has wrapper code for BeOS, OS2, Unix and Windows
-* http://cvs.gnome.org/lxr/source/glib/gmodule/
-*
+** {======================================================
+** 'module' function
+** =======================================================
*/
+
+
+static void setfenv (lua_State *L) {
+ lua_Debug ar;
+ lua_getstack(L, 1, &ar);
+ lua_getinfo(L, "f", &ar);
+ lua_pushvalue(L, -2);
+ lua_setfenv(L, -2);
+ lua_pop(L, 1);
+}
+
+
+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);
+ }
+}
+
+
+static void modinit (lua_State *L, const char *modname) {
+ const char *dot;
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -2, "_M"); /* module._M = module */
+ lua_pushstring(L, modname);
+ lua_setfield(L, -2, "_NAME");
+ dot = strrchr(modname, '.'); /* look for last dot in module name */
+ if (dot == NULL) dot = modname;
+ else dot++;
+ /* set _PACKAGE as package name (full module name minus last part) */
+ lua_pushlstring(L, modname, dot - modname);
+ lua_setfield(L, -2, "_PACKAGE");
+}
+
+
+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 */
+ }
+ /* check whether table already has a _NAME field */
+ lua_getfield(L, -1, "_NAME");
+ if (!lua_isnil(L, -1)) /* is table an initialized module? */
+ lua_pop(L, 1);
+ else { /* no; initialize it */
+ lua_pop(L, 1);
+ modinit(L, modname);
+ }
+ lua_pushvalue(L, -1);
+ setfenv(L);
+ dooptions(L, loaded - 1);
+ return 0;
+}
+
+
+static int ll_seeall (lua_State *L) {
+ luaL_checktype(L, 1, LUA_TTABLE);
+ if (!lua_getmetatable(L, 1)) {
+ lua_createtable(L, 0, 1); /* create new metatable */
+ lua_pushvalue(L, -1);
+ lua_setmetatable(L, 1);
+ }
+ lua_pushvalue(L, LUA_GLOBALSINDEX);
+ lua_setfield(L, -2, "__index"); /* mt.__index = _G */
+ return 0;
+}
+
+
+/* }====================================================== */
+
+
+
+/* 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);
+ if (path == NULL) /* 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);
+ luaL_gsub(L, path, AUXMARK, def);
+ lua_remove(L, -2);
+ }
+ setprogdir(L);
+ lua_setfield(L, -2, fieldname);
+}
+
+
+static const luaL_Reg pk_funcs[] = {
+ {"loadlib", ll_loadlib},
+ {"seeall", ll_seeall},
+ {NULL, NULL}
+};
+
+
+static const luaL_Reg ll_funcs[] = {
+ {"module", ll_module},
+ {"require", ll_require},
+ {NULL, NULL}
+};
+
+
+static const lua_CFunction loaders[] =
+ {loader_preload, loader_Lua, loader_C, loader_Croot, NULL};
+
+
+LUALIB_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]);
+ 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' */
+ /* store config information */
+ lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n"
+ LUA_EXECDIR "\n" LUA_IGMARK);
+ lua_setfield(L, -2, "config");
+ /* set field `loaded' */
+ luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2);
+ lua_setfield(L, -2, "loaded");
+ /* set field `preload' */
+ lua_newtable(L);
+ 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);
+ return 1; /* return 'package' table */
+}
+
diff --git a/lib/lua/src/LuaLib/lstrlib.c b/lib/lua/src/LuaLib/lstrlib.c
index 2e5f26e..8310752 100644
--- a/lib/lua/src/LuaLib/lstrlib.c
+++ b/lib/lua/src/LuaLib/lstrlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lstrlib.c,v 1.4 2004-11-27 21:46:10 pixel Exp $
+** $Id: lstrlib.c,v 1.5 2007-07-27 10:05:55 pixel Exp $
** Standard library for string operations and pattern-matching
** See Copyright Notice in lua.h
*/
@@ -12,6 +12,7 @@
#include <string.h>
#define lstrlib_c
+#define LUA_LIB
#include "lua.h"
@@ -20,35 +21,31 @@
/* macro to `unsign' a character */
-#ifndef uchar
#define uchar(c) ((unsigned char)(c))
-#endif
-
-typedef long sint32; /* a signed version for size_t */
static int str_len (lua_State *L) {
size_t l;
luaL_checklstring(L, 1, &l);
- lua_pushnumber(L, (lua_Number)l);
+ lua_pushinteger(L, l);
return 1;
}
-static sint32 posrelat (sint32 pos, size_t len) {
+static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) {
/* relative string position: negative means back from end */
- return (pos>=0) ? pos : (sint32)len+pos+1;
+ return (pos>=0) ? pos : (ptrdiff_t)len+pos+1;
}
static int str_sub (lua_State *L) {
size_t l;
const char *s = luaL_checklstring(L, 1, &l);
- sint32 start = posrelat(luaL_checklong(L, 2), l);
- sint32 end = posrelat(luaL_optlong(L, 3, -1), l);
+ ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l);
+ ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l);
if (start < 1) start = 1;
- if (end > (sint32)l) end = (sint32)l;
+ if (end > (ptrdiff_t)l) end = (ptrdiff_t)l;
if (start <= end)
lua_pushlstring(L, s+start-1, end-start+1);
else lua_pushliteral(L, "");
@@ -56,6 +53,17 @@ static int str_sub (lua_State *L) {
}
+static int str_reverse (lua_State *L) {
+ size_t l;
+ luaL_Buffer b;
+ const char *s = luaL_checklstring(L, 1, &l);
+ luaL_buffinit(L, &b);
+ while (l--) luaL_addchar(&b, s[l]);
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
static int str_lower (lua_State *L) {
size_t l;
size_t i;
@@ -63,7 +71,7 @@ static int str_lower (lua_State *L) {
const char *s = luaL_checklstring(L, 1, &l);
luaL_buffinit(L, &b);
for (i=0; i<l; i++)
- luaL_putchar(&b, tolower(uchar(s[i])));
+ luaL_addchar(&b, tolower(uchar(s[i])));
luaL_pushresult(&b);
return 1;
}
@@ -76,7 +84,7 @@ static int str_upper (lua_State *L) {
const char *s = luaL_checklstring(L, 1, &l);
luaL_buffinit(L, &b);
for (i=0; i<l; i++)
- luaL_putchar(&b, toupper(uchar(s[i])));
+ luaL_addchar(&b, toupper(uchar(s[i])));
luaL_pushresult(&b);
return 1;
}
@@ -97,11 +105,19 @@ static int str_rep (lua_State *L) {
static int str_byte (lua_State *L) {
size_t l;
const char *s = luaL_checklstring(L, 1, &l);
- sint32 pos = posrelat(luaL_optlong(L, 2, 1), l);
- if (pos <= 0 || (size_t)(pos) > l) /* index out of range? */
- return 0; /* no answer */
- lua_pushnumber(L, uchar(s[pos-1]));
- return 1;
+ ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l);
+ ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l);
+ int n, i;
+ if (posi <= 0) posi = 1;
+ if ((size_t)pose > l) pose = l;
+ if (posi > pose) return 0; /* empty interval; return no values */
+ n = (int)(pose - posi + 1);
+ if (posi + n <= pose) /* overflow? */
+ luaL_error(L, "string slice too long");
+ luaL_checkstack(L, n, "string slice too long");
+ for (i=0; i<n; i++)
+ lua_pushinteger(L, uchar(s[posi+i-1]));
+ return n;
}
@@ -113,7 +129,7 @@ static int str_char (lua_State *L) {
for (i=1; i<=n; i++) {
int c = luaL_checkint(L, i);
luaL_argcheck(L, uchar(c) == c, i, "invalid value");
- luaL_putchar(&b, uchar(c));
+ luaL_addchar(&b, uchar(c));
}
luaL_pushresult(&b);
return 1;
@@ -123,15 +139,16 @@ static int str_char (lua_State *L) {
static int writer (lua_State *L, const void* b, size_t size, void* B) {
(void)L;
luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);
- return 1;
+ return 0;
}
static int str_dump (lua_State *L) {
luaL_Buffer b;
luaL_checktype(L, 1, LUA_TFUNCTION);
+ lua_settop(L, 1);
luaL_buffinit(L,&b);
- if (!lua_dump(L, writer, &b))
+ if (lua_dump(L, writer, &b) != 0)
luaL_error(L, "unable to dump given function");
luaL_pushresult(&b);
return 1;
@@ -145,10 +162,6 @@ static int str_dump (lua_State *L) {
** =======================================================
*/
-#ifndef MAX_CAPTURES
-#define MAX_CAPTURES 32 /* arbitrary limit */
-#endif
-
#define CAP_UNFINISHED (-1)
#define CAP_POSITION (-2)
@@ -160,12 +173,12 @@ typedef struct MatchState {
int level; /* total number of captures (finished or unfinished) */
struct {
const char *init;
- sint32 len;
- } capture[MAX_CAPTURES];
+ ptrdiff_t len;
+ } capture[LUA_MAXCAPTURES];
} MatchState;
-#define ESC '%'
+#define L_ESC '%'
#define SPECIALS "^$*+?.([%-"
@@ -185,19 +198,19 @@ static int capture_to_close (MatchState *ms) {
}
-static const char *luaI_classend (MatchState *ms, const char *p) {
+static const char *classend (MatchState *ms, const char *p) {
switch (*p++) {
- case ESC: {
+ case L_ESC: {
if (*p == '\0')
- luaL_error(ms->L, "malformed pattern (ends with `%')");
+ luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")");
return p+1;
}
case '[': {
if (*p == '^') p++;
do { /* look for a `]' */
if (*p == '\0')
- luaL_error(ms->L, "malformed pattern (missing `]')");
- if (*(p++) == ESC && *p != '\0')
+ luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")");
+ if (*(p++) == L_ESC && *p != '\0')
p++; /* skip escapes (e.g. `%]') */
} while (*p != ']');
return p+1;
@@ -235,9 +248,9 @@ static int matchbracketclass (int c, const char *p, const char *ec) {
p++; /* skip the `^' */
}
while (++p < ec) {
- if (*p == ESC) {
+ if (*p == L_ESC) {
p++;
- if (match_class(c, *p))
+ if (match_class(c, uchar(*p)))
return sig;
}
else if ((*(p+1) == '-') && (p+2 < ec)) {
@@ -251,10 +264,10 @@ static int matchbracketclass (int c, const char *p, const char *ec) {
}
-static int luaI_singlematch (int c, const char *p, const char *ep) {
+static int singlematch (int c, const char *p, const char *ep) {
switch (*p) {
case '.': return 1; /* matches any char */
- case ESC: return match_class(c, *(p+1));
+ case L_ESC: return match_class(c, uchar(*(p+1)));
case '[': return matchbracketclass(c, p, ep-1);
default: return (uchar(*p) == c);
}
@@ -286,8 +299,8 @@ static const char *matchbalance (MatchState *ms, const char *s,
static const char *max_expand (MatchState *ms, const char *s,
const char *p, const char *ep) {
- sint32 i = 0; /* counts maximum expand for item */
- while ((s+i)<ms->src_end && luaI_singlematch(uchar(*(s+i)), p, ep))
+ ptrdiff_t i = 0; /* counts maximum expand for item */
+ while ((s+i)<ms->src_end && singlematch(uchar(*(s+i)), p, ep))
i++;
/* keeps trying to match with the maximum repetitions */
while (i>=0) {
@@ -305,7 +318,7 @@ static const char *min_expand (MatchState *ms, const char *s,
const char *res = match(ms, s, ep+1);
if (res != NULL)
return res;
- else if (s<ms->src_end && luaI_singlematch(uchar(*s), p, ep))
+ else if (s<ms->src_end && singlematch(uchar(*s), p, ep))
s++; /* try with one more repetition */
else return NULL;
}
@@ -316,7 +329,7 @@ static const char *start_capture (MatchState *ms, const char *s,
const char *p, int what) {
const char *res;
int level = ms->level;
- if (level >= MAX_CAPTURES) luaL_error(ms->L, "too many captures");
+ if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures");
ms->capture[level].init = s;
ms->capture[level].len = what;
ms->level = level+1;
@@ -360,7 +373,7 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
case ')': { /* end capture */
return end_capture(ms, s, p+1);
}
- case ESC: {
+ case L_ESC: {
switch (*(p+1)) {
case 'b': { /* balanced string? */
s = matchbalance(ms, s, p+2);
@@ -371,8 +384,9 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
const char *ep; char previous;
p += 2;
if (*p != '[')
- luaL_error(ms->L, "missing `[' after `%%f' in pattern");
- ep = luaI_classend(ms, p); /* points to what is next */
+ luaL_error(ms->L, "missing " LUA_QL("[") " after "
+ LUA_QL("%%f") " in pattern");
+ ep = classend(ms, p); /* points to what is next */
previous = (s == ms->src_init) ? '\0' : *(s-1);
if (matchbracketclass(uchar(previous), p, ep-1) ||
!matchbracketclass(uchar(*s), p, ep-1)) return NULL;
@@ -380,7 +394,7 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
}
default: {
if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */
- s = match_capture(ms, s, *(p+1));
+ s = match_capture(ms, s, uchar(*(p+1)));
if (s == NULL) return NULL;
p+=2; goto init; /* else return match(ms, s, p+2) */
}
@@ -397,8 +411,8 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
else goto dflt;
}
default: dflt: { /* it is a pattern item */
- const char *ep = luaI_classend(ms, p); /* points to what is next */
- int m = s<ms->src_end && luaI_singlematch(uchar(*s), p, ep);
+ const char *ep = classend(ms, p); /* points to what is next */
+ int m = s<ms->src_end && singlematch(uchar(*s), p, ep);
switch (*ep) {
case '?': { /* optional */
const char *res;
@@ -448,45 +462,49 @@ static const char *lmemfind (const char *s1, size_t l1,
}
-static void push_onecapture (MatchState *ms, int i) {
- int l = ms->capture[i].len;
- if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");
- if (l == CAP_POSITION)
- lua_pushnumber(ms->L, (lua_Number)(ms->capture[i].init - ms->src_init + 1));
- else
- lua_pushlstring(ms->L, ms->capture[i].init, l);
+static void push_onecapture (MatchState *ms, int i, const char *s,
+ const char *e) {
+ if (i >= ms->level) {
+ if (i == 0) /* ms->level == 0, too */
+ lua_pushlstring(ms->L, s, e - s); /* add whole match */
+ else
+ luaL_error(ms->L, "invalid capture index");
+ }
+ else {
+ ptrdiff_t l = ms->capture[i].len;
+ if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");
+ if (l == CAP_POSITION)
+ lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1);
+ else
+ lua_pushlstring(ms->L, ms->capture[i].init, l);
+ }
}
static int push_captures (MatchState *ms, const char *s, const char *e) {
int i;
- luaL_checkstack(ms->L, ms->level, "too many captures");
- if (ms->level == 0 && s) { /* no explicit captures? */
- lua_pushlstring(ms->L, s, e-s); /* return whole match */
- return 1;
- }
- else { /* return all captures */
- for (i=0; i<ms->level; i++)
- push_onecapture(ms, i);
- return ms->level; /* number of strings pushed */
- }
+ int nlevels = (ms->level == 0 && s) ? 1 : ms->level;
+ luaL_checkstack(ms->L, nlevels, "too many captures");
+ for (i = 0; i < nlevels; i++)
+ push_onecapture(ms, i, s, e);
+ return nlevels; /* number of strings pushed */
}
-static int str_find (lua_State *L) {
+static int str_find_aux (lua_State *L, int find) {
size_t l1, l2;
const char *s = luaL_checklstring(L, 1, &l1);
const char *p = luaL_checklstring(L, 2, &l2);
- sint32 init = posrelat(luaL_optlong(L, 3, 1), l1) - 1;
+ ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;
if (init < 0) init = 0;
- else if ((size_t)(init) > l1) init = (sint32)l1;
- if (lua_toboolean(L, 4) || /* explicit request? */
- strpbrk(p, SPECIALS) == NULL) { /* or no special characters? */
+ else if ((size_t)(init) > l1) init = (ptrdiff_t)l1;
+ if (find && (lua_toboolean(L, 4) || /* explicit request? */
+ strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */
/* do a plain search */
const char *s2 = lmemfind(s+init, l1-init, p, l2);
if (s2) {
- lua_pushnumber(L, (lua_Number)(s2-s+1));
- lua_pushnumber(L, (lua_Number)(s2-s+l2));
+ lua_pushinteger(L, s2-s+1);
+ lua_pushinteger(L, s2-s+l2);
return 2;
}
}
@@ -501,35 +519,49 @@ static int str_find (lua_State *L) {
const char *res;
ms.level = 0;
if ((res=match(&ms, s1, p)) != NULL) {
- lua_pushnumber(L, (lua_Number)(s1-s+1)); /* start */
- lua_pushnumber(L, (lua_Number)(res-s)); /* end */
- return push_captures(&ms, NULL, 0) + 2;
+ if (find) {
+ lua_pushinteger(L, s1-s+1); /* start */
+ lua_pushinteger(L, res-s); /* end */
+ return push_captures(&ms, NULL, 0) + 2;
+ }
+ else
+ return push_captures(&ms, s1, res);
}
- } while (s1++<ms.src_end && !anchor);
+ } while (s1++ < ms.src_end && !anchor);
}
lua_pushnil(L); /* not found */
return 1;
}
-static int gfind_aux (lua_State *L) {
+static int str_find (lua_State *L) {
+ return str_find_aux(L, 1);
+}
+
+
+static int str_match (lua_State *L) {
+ return str_find_aux(L, 0);
+}
+
+
+static int gmatch_aux (lua_State *L) {
MatchState ms;
- const char *s = lua_tostring(L, lua_upvalueindex(1));
- size_t ls = lua_strlen(L, lua_upvalueindex(1));
+ size_t ls;
+ const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
const char *p = lua_tostring(L, lua_upvalueindex(2));
const char *src;
ms.L = L;
ms.src_init = s;
ms.src_end = s+ls;
- for (src = s + (size_t)lua_tonumber(L, lua_upvalueindex(3));
+ for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3));
src <= ms.src_end;
src++) {
const char *e;
ms.level = 0;
if ((e = match(&ms, src, p)) != NULL) {
- int newstart = e-s;
+ lua_Integer newstart = e-s;
if (e == src) newstart++; /* empty match? go at least one position */
- lua_pushnumber(L, (lua_Number)newstart);
+ lua_pushinteger(L, newstart);
lua_replace(L, lua_upvalueindex(3));
return push_captures(&ms, src, e);
}
@@ -538,48 +570,77 @@ static int gfind_aux (lua_State *L) {
}
-static int gfind (lua_State *L) {
+static int gmatch (lua_State *L) {
luaL_checkstring(L, 1);
luaL_checkstring(L, 2);
lua_settop(L, 2);
- lua_pushnumber(L, 0);
- lua_pushcclosure(L, gfind_aux, 3);
+ lua_pushinteger(L, 0);
+ lua_pushcclosure(L, gmatch_aux, 3);
return 1;
}
-static void add_s (MatchState *ms, luaL_Buffer *b,
- const char *s, const char *e) {
- lua_State *L = ms->L;
- if (lua_isstring(L, 3)) {
- const char *news = lua_tostring(L, 3);
- size_t l = lua_strlen(L, 3);
- size_t i;
- for (i=0; i<l; i++) {
- if (news[i] != ESC)
- luaL_putchar(b, news[i]);
+static int gfind_nodef (lua_State *L) {
+ return luaL_error(L, LUA_QL("string.gfind") " was renamed to "
+ LUA_QL("string.gmatch"));
+}
+
+
+static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
+ const char *e) {
+ size_t l, i;
+ const char *news = lua_tolstring(ms->L, 3, &l);
+ for (i = 0; i < l; i++) {
+ if (news[i] != L_ESC)
+ luaL_addchar(b, news[i]);
+ else {
+ i++; /* skip ESC */
+ if (!isdigit(uchar(news[i])))
+ luaL_addchar(b, news[i]);
+ else if (news[i] == '0')
+ luaL_addlstring(b, s, e - s);
else {
- i++; /* skip ESC */
- if (!isdigit(uchar(news[i])))
- luaL_putchar(b, news[i]);
- else {
- int level = check_capture(ms, news[i]);
- push_onecapture(ms, level);
- luaL_addvalue(b); /* add capture to accumulated result */
- }
+ push_onecapture(ms, news[i] - '1', s, e);
+ luaL_addvalue(b); /* add capture to accumulated result */
}
}
}
- else { /* is a function */
- int n;
- lua_pushvalue(L, 3);
- n = push_captures(ms, s, e);
- lua_call(L, n, 1);
- if (lua_isstring(L, -1))
- luaL_addvalue(b); /* add return to accumulated result */
- else
- lua_pop(L, 1); /* function result is not a string: pop it */
+}
+
+
+static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
+ const char *e) {
+ lua_State *L = ms->L;
+ switch (lua_type(L, 3)) {
+ case LUA_TNUMBER:
+ case LUA_TSTRING: {
+ add_s(ms, b, s, e);
+ return;
+ }
+ case LUA_TFUNCTION: {
+ int n;
+ lua_pushvalue(L, 3);
+ n = push_captures(ms, s, e);
+ lua_call(L, n, 1);
+ break;
+ }
+ case LUA_TTABLE: {
+ push_onecapture(ms, 0, s, e);
+ lua_gettable(L, 3);
+ break;
+ }
+ default: {
+ luaL_argerror(L, 3, "string/function/table expected");
+ return;
+ }
}
+ if (!lua_toboolean(L, -1)) { /* nil or false? */
+ lua_pop(L, 1);
+ lua_pushlstring(L, s, e - s); /* keep original text */
+ }
+ else if (!lua_isstring(L, -1))
+ luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1));
+ luaL_addvalue(b); /* add result to accumulator */
}
@@ -592,9 +653,6 @@ static int str_gsub (lua_State *L) {
int n = 0;
MatchState ms;
luaL_Buffer b;
- luaL_argcheck(L,
- lua_gettop(L) >= 3 && (lua_isstring(L, 3) || lua_isfunction(L, 3)),
- 3, "string or function expected");
luaL_buffinit(L, &b);
ms.L = L;
ms.src_init = src;
@@ -605,18 +663,18 @@ static int str_gsub (lua_State *L) {
e = match(&ms, src, p);
if (e) {
n++;
- add_s(&ms, &b, src, e);
+ add_value(&ms, &b, src, e);
}
if (e && e>src) /* non empty match? */
src = e; /* skip it */
else if (src < ms.src_end)
- luaL_putchar(&b, *src++);
+ luaL_addchar(&b, *src++);
else break;
if (anchor) break;
}
luaL_addlstring(&b, src, ms.src_end-src);
luaL_pushresult(&b);
- lua_pushnumber(L, (lua_Number)n); /* number of substitutions */
+ lua_pushinteger(L, n); /* number of substitutions */
return 2;
}
@@ -625,19 +683,28 @@ static int str_gsub (lua_State *L) {
/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
#define MAX_ITEM 512
-/* maximum size of each format specification (such as '%-099.99d') */
-#define MAX_FORMAT 20
+/* valid flags in a format specification */
+#define FLAGS "-+ #0"
+/*
+** maximum size of each format specification (such as '%-099.99d')
+** (+10 accounts for %99.99x plus margin of error)
+*/
+#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)
-static void luaI_addquoted (lua_State *L, luaL_Buffer *b, int arg) {
+static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
size_t l;
const char *s = luaL_checklstring(L, arg, &l);
- luaL_putchar(b, '"');
+ luaL_addchar(b, '"');
while (l--) {
switch (*s) {
case '"': case '\\': case '\n': {
- luaL_putchar(b, '\\');
- luaL_putchar(b, *s);
+ luaL_addchar(b, '\\');
+ luaL_addchar(b, *s);
+ break;
+ }
+ case '\r': {
+ luaL_addlstring(b, "\\r", 2);
break;
}
case '\0': {
@@ -645,39 +712,46 @@ static void luaI_addquoted (lua_State *L, luaL_Buffer *b, int arg) {
break;
}
default: {
- luaL_putchar(b, *s);
+ luaL_addchar(b, *s);
break;
}
}
s++;
}
- luaL_putchar(b, '"');
+ luaL_addchar(b, '"');
}
-
-static const char *scanformat (lua_State *L, const char *strfrmt,
- char *form, int *hasprecision) {
+static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
const char *p = strfrmt;
- while (strchr("-+ #0", *p)) p++; /* skip flags */
+ while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */
+ if ((size_t)(p - strfrmt) >= sizeof(FLAGS))
+ luaL_error(L, "invalid format (repeated flags)");
if (isdigit(uchar(*p))) p++; /* skip width */
if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
if (*p == '.') {
p++;
- *hasprecision = 1;
if (isdigit(uchar(*p))) p++; /* skip precision */
if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
}
if (isdigit(uchar(*p)))
luaL_error(L, "invalid format (width or precision too long)");
- if (p-strfrmt+2 > MAX_FORMAT) /* +2 to include `%' and the specifier */
- luaL_error(L, "invalid format (too long)");
- form[0] = '%';
- strncpy(form+1, strfrmt, p-strfrmt+1);
- form[p-strfrmt+2] = 0;
+ *(form++) = '%';
+ strncpy(form, strfrmt, p - strfrmt + 1);
+ form += p - strfrmt + 1;
+ *form = '\0';
return p;
}
+static void addintlen (char *form) {
+ size_t l = strlen(form);
+ char spec = form[l - 1];
+ strcpy(form + l - 1, LUA_INTFRMLEN);
+ form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;
+ form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0';
+}
+
+
static int str_format (lua_State *L) {
int arg = 1;
size_t sfl;
@@ -686,40 +760,43 @@ static int str_format (lua_State *L) {
luaL_Buffer b;
luaL_buffinit(L, &b);
while (strfrmt < strfrmt_end) {
- if (*strfrmt != '%')
- luaL_putchar(&b, *strfrmt++);
- else if (*++strfrmt == '%')
- luaL_putchar(&b, *strfrmt++); /* %% */
+ if (*strfrmt != L_ESC)
+ luaL_addchar(&b, *strfrmt++);
+ else if (*++strfrmt == L_ESC)
+ luaL_addchar(&b, *strfrmt++); /* %% */
else { /* format item */
char form[MAX_FORMAT]; /* to store the format (`%...') */
char buff[MAX_ITEM]; /* to store the formatted item */
- int hasprecision = 0;
- if (isdigit(uchar(*strfrmt)) && *(strfrmt+1) == '$')
- return luaL_error(L, "obsolete option (d$) to `format'");
arg++;
- strfrmt = scanformat(L, strfrmt, form, &hasprecision);
+ strfrmt = scanformat(L, strfrmt, form);
switch (*strfrmt++) {
- case 'c': case 'd': case 'i': {
- sprintf(buff, form, luaL_checkint(L, arg));
+ case 'c': {
+ sprintf(buff, form, (int)luaL_checknumber(L, arg));
+ break;
+ }
+ case 'd': case 'i': {
+ addintlen(form);
+ sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg));
break;
}
case 'o': case 'u': case 'x': case 'X': {
- sprintf(buff, form, (unsigned int)(luaL_checknumber(L, arg)));
+ addintlen(form);
+ sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));
break;
}
case 'e': case 'E': case 'f':
case 'g': case 'G': {
- sprintf(buff, form, luaL_checknumber(L, arg));
+ sprintf(buff, form, (double)luaL_checknumber(L, arg));
break;
}
case 'q': {
- luaI_addquoted(L, &b, arg);
- continue; /* skip the `addsize' at the end */
+ addquoted(L, &b, arg);
+ continue; /* skip the 'addsize' at the end */
}
case 's': {
size_t l;
const char *s = luaL_checklstring(L, arg, &l);
- if (!hasprecision && l >= 100) {
+ if (!strchr(form, '.') && l >= 100) {
/* no precision and string is too long to be formatted;
keep original string */
lua_pushvalue(L, arg);
@@ -732,7 +809,8 @@ static int str_format (lua_State *L) {
}
}
default: { /* also treat cases `pnLlh' */
- return luaL_error(L, "invalid option to `format'");
+ return luaL_error(L, "invalid option " LUA_QL("%%%c") " to "
+ LUA_QL("format"), *(strfrmt - 1));
}
}
luaL_addlstring(&b, buff, strlen(buff));
@@ -743,28 +821,48 @@ static int str_format (lua_State *L) {
}
-static const luaL_reg strlib[] = {
- {"len", str_len},
- {"sub", str_sub},
- {"lower", str_lower},
- {"upper", str_upper},
- {"char", str_char},
- {"rep", str_rep},
+static const luaL_Reg strlib[] = {
{"byte", str_byte},
- {"format", str_format},
+ {"char", str_char},
{"dump", str_dump},
{"find", str_find},
- {"gfind", gfind},
+ {"format", str_format},
+ {"gfind", gfind_nodef},
+ {"gmatch", gmatch},
{"gsub", str_gsub},
+ {"len", str_len},
+ {"lower", str_lower},
+ {"match", str_match},
+ {"rep", str_rep},
+ {"reverse", str_reverse},
+ {"sub", str_sub},
+ {"upper", str_upper},
{NULL, NULL}
};
+static void createmetatable (lua_State *L) {
+ lua_createtable(L, 0, 1); /* create metatable for strings */
+ lua_pushliteral(L, ""); /* dummy string */
+ lua_pushvalue(L, -2);
+ lua_setmetatable(L, -2); /* set string metatable */
+ lua_pop(L, 1); /* pop dummy string */
+ lua_pushvalue(L, -2); /* string library... */
+ lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */
+ lua_pop(L, 1); /* pop metatable */
+}
+
+
/*
** Open string library
*/
LUALIB_API int luaopen_string (lua_State *L) {
- luaL_openlib(L, LUA_STRLIBNAME, strlib, 0);
+ luaL_register(L, LUA_STRLIBNAME, strlib);
+#if defined(LUA_COMPAT_GFIND)
+ lua_getfield(L, -1, "gmatch");
+ lua_setfield(L, -2, "gfind");
+#endif
+ createmetatable(L);
return 1;
}
diff --git a/lib/lua/src/LuaLib/ltablib.c b/lib/lua/src/LuaLib/ltablib.c
index 71f3afa..6bd11fb 100644
--- a/lib/lua/src/LuaLib/ltablib.c
+++ b/lib/lua/src/LuaLib/ltablib.c
@@ -1,5 +1,5 @@
/*
-** $Id: ltablib.c,v 1.4 2004-11-27 21:46:10 pixel Exp $
+** $Id: ltablib.c,v 1.5 2007-07-27 10:05:55 pixel Exp $
** Library for Table Manipulation
** See Copyright Notice in lua.h
*/
@@ -8,6 +8,7 @@
#include <stddef.h>
#define ltablib_c
+#define LUA_LIB
#include "lua.h"
@@ -18,13 +19,13 @@
#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n))
-static int luaB_foreachi (lua_State *L) {
+static int foreachi (lua_State *L) {
int i;
int n = aux_getn(L, 1);
luaL_checktype(L, 2, LUA_TFUNCTION);
- for (i=1; i<=n; i++) {
+ for (i=1; i <= n; i++) {
lua_pushvalue(L, 2); /* function */
- lua_pushnumber(L, (lua_Number)i); /* 1st argument */
+ lua_pushinteger(L, i); /* 1st argument */
lua_rawgeti(L, 1, i); /* 2nd argument */
lua_call(L, 2, 1);
if (!lua_isnil(L, -1))
@@ -35,13 +36,11 @@ static int luaB_foreachi (lua_State *L) {
}
-static int luaB_foreach (lua_State *L) {
+static int foreach (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
luaL_checktype(L, 2, LUA_TFUNCTION);
lua_pushnil(L); /* first key */
- for (;;) {
- if (lua_next(L, 1) == 0)
- return 0;
+ while (lua_next(L, 1)) {
lua_pushvalue(L, 2); /* function */
lua_pushvalue(L, -3); /* key */
lua_pushvalue(L, -3); /* value */
@@ -50,74 +49,102 @@ static int luaB_foreach (lua_State *L) {
return 1;
lua_pop(L, 2); /* remove value and result */
}
+ return 0;
+}
+
+
+static int maxn (lua_State *L) {
+ lua_Number max = 0;
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_pushnil(L); /* first key */
+ while (lua_next(L, 1)) {
+ lua_pop(L, 1); /* remove value */
+ if (lua_type(L, -1) == LUA_TNUMBER) {
+ lua_Number v = lua_tonumber(L, -1);
+ if (v > max) max = v;
+ }
+ }
+ lua_pushnumber(L, max);
+ return 1;
}
-static int luaB_getn (lua_State *L) {
- lua_pushnumber(L, (lua_Number)aux_getn(L, 1));
+static int getn (lua_State *L) {
+ lua_pushinteger(L, aux_getn(L, 1));
return 1;
}
-static int luaB_setn (lua_State *L) {
+static int setn (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
+#ifndef luaL_setn
luaL_setn(L, 1, luaL_checkint(L, 2));
- return 0;
+#else
+ luaL_error(L, LUA_QL("setn") " is obsolete");
+#endif
+ lua_pushvalue(L, 1);
+ return 1;
}
-static int luaB_tinsert (lua_State *L) {
- int v = lua_gettop(L); /* number of arguments */
- int n = aux_getn(L, 1) + 1;
+static int tinsert (lua_State *L) {
+ int e = aux_getn(L, 1) + 1; /* first empty element */
int pos; /* where to insert new element */
- if (v == 2) /* called with only 2 arguments */
- pos = n; /* insert new element at the end */
- else {
- pos = luaL_checkint(L, 2); /* 2nd argument is the position */
- if (pos > n) n = pos; /* `grow' array if necessary */
- v = 3; /* function may be called with more than 3 args */
- }
- luaL_setn(L, 1, n); /* new size */
- while (--n >= pos) { /* move up elements */
- lua_rawgeti(L, 1, n);
- lua_rawseti(L, 1, n+1); /* t[n+1] = t[n] */
+ switch (lua_gettop(L)) {
+ case 2: { /* called with only 2 arguments */
+ pos = e; /* insert new element at the end */
+ break;
+ }
+ case 3: {
+ int i;
+ pos = luaL_checkint(L, 2); /* 2nd argument is the position */
+ if (pos > e) e = pos; /* `grow' array if necessary */
+ for (i = e; i > pos; i--) { /* move up elements */
+ lua_rawgeti(L, 1, i-1);
+ lua_rawseti(L, 1, i); /* t[i] = t[i-1] */
+ }
+ break;
+ }
+ default: {
+ return luaL_error(L, "wrong number of arguments to " LUA_QL("insert"));
+ }
}
- lua_pushvalue(L, v);
+ luaL_setn(L, 1, e); /* new size */
lua_rawseti(L, 1, pos); /* t[pos] = v */
return 0;
}
-static int luaB_tremove (lua_State *L) {
- int n = aux_getn(L, 1);
- int pos = luaL_optint(L, 2, n);
- if (n <= 0) return 0; /* table is `empty' */
- luaL_setn(L, 1, n-1); /* t.n = n-1 */
+static int tremove (lua_State *L) {
+ int e = aux_getn(L, 1);
+ int pos = luaL_optint(L, 2, e);
+ if (e == 0) return 0; /* table is `empty' */
+ luaL_setn(L, 1, e - 1); /* t.n = n-1 */
lua_rawgeti(L, 1, pos); /* result = t[pos] */
- for ( ;pos<n; pos++) {
+ for ( ;pos<e; pos++) {
lua_rawgeti(L, 1, pos+1);
lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */
}
lua_pushnil(L);
- lua_rawseti(L, 1, n); /* t[n] = nil */
+ lua_rawseti(L, 1, e); /* t[e] = nil */
return 1;
}
-static int str_concat (lua_State *L) {
+static int tconcat (lua_State *L) {
luaL_Buffer b;
size_t lsep;
+ int i, last;
const char *sep = luaL_optlstring(L, 2, "", &lsep);
- int i = luaL_optint(L, 3, 1);
- int n = luaL_optint(L, 4, 0);
luaL_checktype(L, 1, LUA_TTABLE);
- if (n == 0) n = luaL_getn(L, 1);
+ i = luaL_optint(L, 3, 1);
+ last = luaL_opt(L, luaL_checkint, 4, luaL_getn(L, 1));
luaL_buffinit(L, &b);
- for (; i <= n; i++) {
+ for (; i <= last; i++) {
lua_rawgeti(L, 1, i);
luaL_argcheck(L, lua_isstring(L, -1), 1, "table contains non-strings");
luaL_addvalue(&b);
- if (i != n)
+ if (i != last)
luaL_addlstring(&b, sep, lsep);
}
luaL_pushresult(&b);
@@ -217,7 +244,7 @@ static void auxsort (lua_State *L, int l, int u) {
} /* repeat the routine for the larger one */
}
-static int luaB_sort (lua_State *L) {
+static int sort (lua_State *L) {
int n = aux_getn(L, 1);
luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */
if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */
@@ -230,21 +257,22 @@ static int luaB_sort (lua_State *L) {
/* }====================================================== */
-static const luaL_reg tab_funcs[] = {
- {"concat", str_concat},
- {"foreach", luaB_foreach},
- {"foreachi", luaB_foreachi},
- {"getn", luaB_getn},
- {"setn", luaB_setn},
- {"sort", luaB_sort},
- {"insert", luaB_tinsert},
- {"remove", luaB_tremove},
+static const luaL_Reg tab_funcs[] = {
+ {"concat", tconcat},
+ {"foreach", foreach},
+ {"foreachi", foreachi},
+ {"getn", getn},
+ {"maxn", maxn},
+ {"insert", tinsert},
+ {"remove", tremove},
+ {"setn", setn},
+ {"sort", sort},
{NULL, NULL}
};
LUALIB_API int luaopen_table (lua_State *L) {
- luaL_openlib(L, LUA_TABLIBNAME, tab_funcs, 0);
+ luaL_register(L, LUA_TABLIBNAME, tab_funcs);
return 1;
}
diff --git a/lib/lua/src/lapi.c b/lib/lua/src/lapi.c
index 7298b87..e456c8f 100644
--- a/lib/lua/src/lapi.c
+++ b/lib/lua/src/lapi.c
@@ -1,14 +1,17 @@
/*
-** $Id: lapi.c,v 1.5 2007-07-25 16:54:32 pixel Exp $
+** $Id: lapi.c,v 1.6 2007-07-27 10:05:53 pixel Exp $
** Lua API
** See Copyright Notice in lua.h
*/
#include <assert.h>
+#include <math.h>
+#include <stdarg.h>
#include <string.h>
#define lapi_c
+#define LUA_CORE
#include "lua.h"
@@ -27,79 +30,72 @@
#include "lvm.h"
+
const char lua_ident[] =
- "$Lua: " LUA_VERSION " " LUA_COPYRIGHT " $\n"
+ "$Lua: " LUA_RELEASE " " LUA_COPYRIGHT " $\n"
"$Authors: " LUA_AUTHORS " $\n"
"$URL: www.lua.org $\n";
-#ifndef api_check
-#define api_check(L, o) /*{ assert(o); }*/
-#endif
-
#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base))
-#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;}
+#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject)
+#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;}
-static TObject *negindex (lua_State *L, int idx) {
- if (idx > LUA_REGISTRYINDEX) {
+static TValue *index2adr (lua_State *L, int idx) {
+ if (idx > 0) {
+ TValue *o = L->base + (idx - 1);
+ api_check(L, idx <= L->ci->top - L->base);
+ if (o >= L->top) return cast(TValue *, luaO_nilobject);
+ else return o;
+ }
+ else if (idx > LUA_REGISTRYINDEX) {
api_check(L, idx != 0 && -idx <= L->top - L->base);
- return L->top+idx;
+ return L->top + idx;
}
else switch (idx) { /* pseudo-indices */
case LUA_REGISTRYINDEX: return registry(L);
+ case LUA_ENVIRONINDEX: {
+ Closure *func = curr_func(L);
+ sethvalue(L, &L->env, func->c.env);
+ return &L->env;
+ }
case LUA_GLOBALSINDEX: return gt(L);
default: {
- TObject *func = (L->base - 1);
+ Closure *func = curr_func(L);
idx = LUA_GLOBALSINDEX - idx;
- lua_assert(iscfunction(func));
- return (idx <= clvalue(func)->c.nupvalues)
- ? &clvalue(func)->c.upvalue[idx-1]
- : NULL;
+ return (idx <= func->c.nupvalues)
+ ? &func->c.upvalue[idx-1]
+ : cast(TValue *, luaO_nilobject);
}
}
}
-static TObject *luaA_index (lua_State *L, int idx) {
- if (idx > 0) {
- api_check(L, idx <= L->top - L->base);
- return L->base + idx - 1;
- }
+static Table *getcurrenv (lua_State *L) {
+ if (L->ci == L->base_ci) /* no enclosing function? */
+ return hvalue(gt(L)); /* use global table as environment */
else {
- TObject *o = negindex(L, idx);
- api_check(L, o != NULL);
- return o;
+ Closure *func = curr_func(L);
+ return func->c.env;
}
}
-static TObject *luaA_indexAcceptable (lua_State *L, int idx) {
- if (idx > 0) {
- TObject *o = L->base+(idx-1);
- api_check(L, idx <= L->stack_last - L->base);
- if (o >= L->top) return NULL;
- else return o;
- }
- else
- return negindex(L, idx);
-}
-
-
-void luaA_pushobject (lua_State *L, const TObject *o) {
- setobj2s(L->top, o);
- incr_top(L);
+void luaA_pushobject (lua_State *L, const TValue *o) {
+ setobj2s(L, L->top, o);
+ api_incr_top(L);
}
LUA_API int lua_checkstack (lua_State *L, int size) {
int res;
lua_lock(L);
- if ((L->top - L->base + size) > LUA_MAXCSTACK)
+ if ((L->top - L->base + size) > LUAI_MAXCSTACK)
res = 0; /* stack overflow */
else {
luaD_checkstack(L, size);
@@ -114,12 +110,14 @@ LUA_API int lua_checkstack (lua_State *L, int size) {
LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
int i;
+ if (from == to) return;
lua_lock(to);
api_checknelems(from, n);
+ api_check(from, G(from) == G(to));
+ api_check(from, to->ci->top - to->top >= n);
from->top -= n;
for (i = 0; i < n; i++) {
- setobj2s(to->top, from->top + i);
- api_incr_top(to);
+ setobj2s(to, to->top++, from->top + i);
}
lua_unlock(to);
}
@@ -140,10 +138,10 @@ LUA_API lua_State *lua_newthread (lua_State *L) {
lua_lock(L);
luaC_checkGC(L);
L1 = luaE_newthread(L);
- setthvalue(L->top, L1);
+ setthvalue(L, L->top, L1);
api_incr_top(L);
lua_unlock(L);
- lua_userstateopen(L1);
+ luai_userstatethread(L, L1);
return L1;
}
@@ -155,7 +153,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) {
LUA_API int lua_gettop (lua_State *L) {
- return (L->top - L->base);
+ return cast_int(L->top - L->base);
}
@@ -178,8 +176,9 @@ LUA_API void lua_settop (lua_State *L, int idx) {
LUA_API void lua_remove (lua_State *L, int idx) {
StkId p;
lua_lock(L);
- p = luaA_index(L, idx);
- while (++p < L->top) setobjs2s(p-1, p);
+ p = index2adr(L, idx);
+ api_checkvalidindex(L, p);
+ while (++p < L->top) setobjs2s(L, p-1, p);
L->top--;
lua_unlock(L);
}
@@ -189,17 +188,34 @@ LUA_API void lua_insert (lua_State *L, int idx) {
StkId p;
StkId q;
lua_lock(L);
- p = luaA_index(L, idx);
- for (q = L->top; q>p; q--) setobjs2s(q, q-1);
- setobjs2s(p, L->top);
+ p = index2adr(L, idx);
+ api_checkvalidindex(L, p);
+ for (q = L->top; q>p; q--) setobjs2s(L, q, q-1);
+ setobjs2s(L, p, L->top);
lua_unlock(L);
}
LUA_API void lua_replace (lua_State *L, int idx) {
+ StkId o;
lua_lock(L);
+ /* explicit test for incompatible code */
+ if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci)
+ luaG_runerror(L, "no calling environment");
api_checknelems(L, 1);
- setobj(luaA_index(L, idx), L->top - 1); /* write barrier */
+ o = index2adr(L, idx);
+ api_checkvalidindex(L, o);
+ if (idx == LUA_ENVIRONINDEX) {
+ Closure *func = curr_func(L);
+ api_check(L, ttistable(L->top - 1));
+ func->c.env = hvalue(L->top - 1);
+ luaC_barrier(L, func, L->top - 1);
+ }
+ else {
+ setobj(L, o, L->top - 1);
+ if (idx < LUA_GLOBALSINDEX) /* function upvalue? */
+ luaC_barrier(L, curr_func(L), L->top - 1);
+ }
L->top--;
lua_unlock(L);
}
@@ -207,7 +223,7 @@ LUA_API void lua_replace (lua_State *L, int idx) {
LUA_API void lua_pushvalue (lua_State *L, int idx) {
lua_lock(L);
- setobj2s(L->top, luaA_index(L, idx));
+ setobj2s(L, L->top, index2adr(L, idx));
api_incr_top(L);
lua_unlock(L);
}
@@ -220,8 +236,8 @@ LUA_API void lua_pushvalue (lua_State *L, int idx) {
LUA_API int lua_type (lua_State *L, int idx) {
- StkId o = luaA_indexAcceptable(L, idx);
- return (o == NULL) ? LUA_TNONE : ttype(o);
+ StkId o = index2adr(L, idx);
+ return (o == luaO_nilobject) ? LUA_TNONE : ttype(o);
}
@@ -232,15 +248,15 @@ LUA_API const char *lua_typename (lua_State *L, int t) {
LUA_API int lua_iscfunction (lua_State *L, int idx) {
- StkId o = luaA_indexAcceptable(L, idx);
- return (o == NULL) ? 0 : iscfunction(o);
+ StkId o = index2adr(L, idx);
+ return iscfunction(o);
}
LUA_API int lua_isnumber (lua_State *L, int idx) {
- TObject n;
- const TObject *o = luaA_indexAcceptable(L, idx);
- return (o != NULL && tonumber(o, &n));
+ TValue n;
+ const TValue *o = index2adr(L, idx);
+ return tonumber(o, &n);
}
@@ -251,16 +267,16 @@ LUA_API int lua_isstring (lua_State *L, int idx) {
LUA_API int lua_isuserdata (lua_State *L, int idx) {
- const TObject *o = luaA_indexAcceptable(L, idx);
- return (o != NULL && (ttisuserdata(o) || ttislightuserdata(o)));
+ const TValue *o = index2adr(L, idx);
+ return (ttisuserdata(o) || ttislightuserdata(o));
}
LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
- StkId o1 = luaA_indexAcceptable(L, index1);
- StkId o2 = luaA_indexAcceptable(L, index2);
- return (o1 == NULL || o2 == NULL) ? 0 /* index out of range */
- : luaO_rawequalObj(o1, o2);
+ StkId o1 = index2adr(L, index1);
+ StkId o2 = index2adr(L, index2);
+ return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0
+ : luaO_rawequalObj(o1, o2);
}
@@ -268,10 +284,9 @@ LUA_API int lua_equal (lua_State *L, int index1, int index2) {
StkId o1, o2;
int i;
lua_lock(L); /* may call tag method */
- o1 = luaA_indexAcceptable(L, index1);
- o2 = luaA_indexAcceptable(L, index2);
- i = (o1 == NULL || o2 == NULL) ? 0 /* index out of range */
- : equalobj(L, o1, o2);
+ o1 = index2adr(L, index1);
+ o2 = index2adr(L, index2);
+ i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2);
lua_unlock(L);
return i;
}
@@ -281,10 +296,10 @@ LUA_API int lua_lessthan (lua_State *L, int index1, int index2) {
StkId o1, o2;
int i;
lua_lock(L); /* may call tag method */
- o1 = luaA_indexAcceptable(L, index1);
- o2 = luaA_indexAcceptable(L, index2);
- i = (o1 == NULL || o2 == NULL) ? 0 /* index out-of-range */
- : luaV_lessthan(L, o1, o2);
+ o1 = index2adr(L, index1);
+ o2 = index2adr(L, index2);
+ i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0
+ : luaV_lessthan(L, o1, o2);
lua_unlock(L);
return i;
}
@@ -292,65 +307,81 @@ LUA_API int lua_lessthan (lua_State *L, int index1, int index2) {
LUA_API lua_Number lua_tonumber (lua_State *L, int idx) {
- TObject n;
- const TObject *o = luaA_indexAcceptable(L, idx);
- if (o != NULL && tonumber(o, &n))
+ TValue n;
+ const TValue *o = index2adr(L, idx);
+ if (tonumber(o, &n))
return nvalue(o);
else
return 0;
}
+LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) {
+ TValue n;
+ const TValue *o = index2adr(L, idx);
+ if (tonumber(o, &n)) {
+ lua_Integer res;
+ lua_Number num = nvalue(o);
+ lua_number2integer(res, num);
+ return res;
+ }
+ else
+ return 0;
+}
+
+
LUA_API int lua_toboolean (lua_State *L, int idx) {
- const TObject *o = luaA_indexAcceptable(L, idx);
- return (o != NULL) && !l_isfalse(o);
+ const TValue *o = index2adr(L, idx);
+ return !l_isfalse(o);
}
-LUA_API const char *lua_tostring (lua_State *L, int idx) {
- StkId o = luaA_indexAcceptable(L, idx);
- if (o == NULL)
- return NULL;
- else if (ttisstring(o))
- return svalue(o);
- else {
- const char *s;
+LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
+ StkId o = index2adr(L, idx);
+ if (!ttisstring(o)) {
lua_lock(L); /* `luaV_tostring' may create a new string */
- s = (luaV_tostring(L, o) ? svalue(o) : NULL);
+ if (!luaV_tostring(L, o)) { /* conversion failed? */
+ if (len != NULL) *len = 0;
+ lua_unlock(L);
+ return NULL;
+ }
luaC_checkGC(L);
+ o = index2adr(L, idx); /* previous call may reallocate the stack */
lua_unlock(L);
- return s;
}
+ if (len != NULL) *len = tsvalue(o)->len;
+ return svalue(o);
}
-LUA_API size_t lua_strlen (lua_State *L, int idx) {
- StkId o = luaA_indexAcceptable(L, idx);
- if (o == NULL)
- return 0;
- else if (ttisstring(o))
- return tsvalue(o)->tsv.len;
- else {
- size_t l;
- lua_lock(L); /* `luaV_tostring' may create a new string */
- l = (luaV_tostring(L, o) ? tsvalue(o)->tsv.len : 0);
- lua_unlock(L);
- return l;
+LUA_API size_t lua_objlen (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+ switch (ttype(o)) {
+ case LUA_TSTRING: return tsvalue(o)->len;
+ case LUA_TUSERDATA: return uvalue(o)->len;
+ case LUA_TTABLE: return luaH_getn(hvalue(o));
+ case LUA_TNUMBER: {
+ size_t l;
+ lua_lock(L); /* `luaV_tostring' may create a new string */
+ l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0);
+ lua_unlock(L);
+ return l;
+ }
+ default: return 0;
}
}
LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {
- StkId o = luaA_indexAcceptable(L, idx);
- return (o == NULL || !iscfunction(o)) ? NULL : clvalue(o)->c.f;
+ StkId o = index2adr(L, idx);
+ return (!iscfunction(o)) ? NULL : clvalue(o)->c.f;
}
LUA_API void *lua_touserdata (lua_State *L, int idx) {
- StkId o = luaA_indexAcceptable(L, idx);
- if (o == NULL) return NULL;
+ StkId o = index2adr(L, idx);
switch (ttype(o)) {
- case LUA_TUSERDATA: return (uvalue(o) + 1);
+ case LUA_TUSERDATA: return (rawuvalue(o) + 1);
case LUA_TLIGHTUSERDATA: return pvalue(o);
default: return NULL;
}
@@ -358,24 +389,21 @@ LUA_API void *lua_touserdata (lua_State *L, int idx) {
LUA_API lua_State *lua_tothread (lua_State *L, int idx) {
- StkId o = luaA_indexAcceptable(L, idx);
- return (o == NULL || !ttisthread(o)) ? NULL : thvalue(o);
+ StkId o = index2adr(L, idx);
+ return (!ttisthread(o)) ? NULL : thvalue(o);
}
LUA_API const void *lua_topointer (lua_State *L, int idx) {
- StkId o = luaA_indexAcceptable(L, idx);
- if (o == NULL) return NULL;
- else {
- switch (ttype(o)) {
- case LUA_TTABLE: return hvalue(o);
- case LUA_TFUNCTION: return clvalue(o);
- case LUA_TTHREAD: return thvalue(o);
- case LUA_TUSERDATA:
- case LUA_TLIGHTUSERDATA:
- return lua_touserdata(L, idx);
- default: return NULL;
- }
+ StkId o = index2adr(L, idx);
+ switch (ttype(o)) {
+ case LUA_TTABLE: return hvalue(o);
+ case LUA_TFUNCTION: return clvalue(o);
+ case LUA_TTHREAD: return thvalue(o);
+ case LUA_TUSERDATA:
+ case LUA_TLIGHTUSERDATA:
+ return lua_touserdata(L, idx);
+ default: return NULL;
}
}
@@ -402,10 +430,18 @@ LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
}
+LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
+ lua_lock(L);
+ setnvalue(L->top, cast_num(n));
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
lua_lock(L);
luaC_checkGC(L);
- setsvalue2s(L->top, luaS_newlstr(L, s, len));
+ setsvalue2s(L, L->top, luaS_newlstr(L, s, len));
api_incr_top(L);
lua_unlock(L);
}
@@ -448,12 +484,13 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
lua_lock(L);
luaC_checkGC(L);
api_checknelems(L, n);
- cl = luaF_newCclosure(L, n);
+ cl = luaF_newCclosure(L, n, getcurrenv(L));
cl->c.f = fn;
L->top -= n;
while (n--)
- setobj2n(&cl->c.upvalue[n], L->top+n);
- setclvalue(L->top, cl);
+ setobj2n(L, &cl->c.upvalue[n], L->top+n);
+ setclvalue(L, L->top, cl);
+ lua_assert(iswhite(obj2gco(cl)));
api_incr_top(L);
lua_unlock(L);
}
@@ -475,6 +512,15 @@ LUA_API void lua_pushlightuserdata (lua_State *L, void *p) {
}
+LUA_API int lua_pushthread (lua_State *L) {
+ lua_lock(L);
+ setthvalue(L, L->top, L);
+ api_incr_top(L);
+ lua_unlock(L);
+ return (G(L)->mainthread == L);
+}
+
+
/*
** get functions (Lua -> stack)
@@ -484,8 +530,22 @@ LUA_API void lua_pushlightuserdata (lua_State *L, void *p) {
LUA_API void lua_gettable (lua_State *L, int idx) {
StkId t;
lua_lock(L);
- t = luaA_index(L, idx);
- setobj2s(L->top - 1, luaV_gettable(L, t, L->top - 1, 0));
+ t = index2adr(L, idx);
+ api_checkvalidindex(L, t);
+ luaV_gettable(L, t, L->top - 1, L->top - 1);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_getfield (lua_State *L, int idx, const char *k) {
+ StkId t;
+ TValue key;
+ lua_lock(L);
+ t = index2adr(L, idx);
+ api_checkvalidindex(L, t);
+ setsvalue(L, &key, luaS_new(L, k));
+ luaV_gettable(L, t, &key, L->top);
+ api_incr_top(L);
lua_unlock(L);
}
@@ -493,9 +553,9 @@ LUA_API void lua_gettable (lua_State *L, int idx) {
LUA_API void lua_rawget (lua_State *L, int idx) {
StkId t;
lua_lock(L);
- t = luaA_index(L, idx);
+ t = index2adr(L, idx);
api_check(L, ttistable(t));
- setobj2s(L->top - 1, luaH_get(hvalue(t), L->top - 1));
+ setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));
lua_unlock(L);
}
@@ -503,43 +563,44 @@ LUA_API void lua_rawget (lua_State *L, int idx) {
LUA_API void lua_rawgeti (lua_State *L, int idx, int n) {
StkId o;
lua_lock(L);
- o = luaA_index(L, idx);
+ o = index2adr(L, idx);
api_check(L, ttistable(o));
- setobj2s(L->top, luaH_getnum(hvalue(o), n));
+ setobj2s(L, L->top, luaH_getnum(hvalue(o), n));
api_incr_top(L);
lua_unlock(L);
}
-LUA_API void lua_newtable (lua_State *L) {
+LUA_API void lua_createtable (lua_State *L, int narray, int nrec) {
lua_lock(L);
luaC_checkGC(L);
- sethvalue(L->top, luaH_new(L, 0, 0));
+ sethvalue(L, L->top, luaH_new(L, narray, nrec));
api_incr_top(L);
lua_unlock(L);
}
LUA_API int lua_getmetatable (lua_State *L, int objindex) {
- const TObject *obj;
+ const TValue *obj;
Table *mt = NULL;
int res;
lua_lock(L);
- obj = luaA_indexAcceptable(L, objindex);
- if (obj != NULL) {
- switch (ttype(obj)) {
- case LUA_TTABLE:
- mt = hvalue(obj)->metatable;
- break;
- case LUA_TUSERDATA:
- mt = uvalue(obj)->uv.metatable;
- break;
- }
+ obj = index2adr(L, objindex);
+ switch (ttype(obj)) {
+ case LUA_TTABLE:
+ mt = hvalue(obj)->metatable;
+ break;
+ case LUA_TUSERDATA:
+ mt = uvalue(obj)->metatable;
+ break;
+ default:
+ mt = G(L)->mt[ttype(obj)];
+ break;
}
- if (mt == NULL || mt == hvalue(defaultmeta(L)))
+ if (mt == NULL)
res = 0;
else {
- sethvalue(L->top, mt);
+ sethvalue(L, L->top, mt);
api_incr_top(L);
res = 1;
}
@@ -551,8 +612,22 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) {
LUA_API void lua_getfenv (lua_State *L, int idx) {
StkId o;
lua_lock(L);
- o = luaA_index(L, idx);
- setobj2s(L->top, isLfunction(o) ? &clvalue(o)->l.g : gt(L));
+ o = index2adr(L, idx);
+ api_checkvalidindex(L, o);
+ switch (ttype(o)) {
+ case LUA_TFUNCTION:
+ sethvalue(L, L->top, clvalue(o)->c.env);
+ break;
+ case LUA_TUSERDATA:
+ sethvalue(L, L->top, uvalue(o)->env);
+ break;
+ case LUA_TTHREAD:
+ setobj2s(L, L->top, gt(thvalue(o)));
+ break;
+ default:
+ setnilvalue(L->top);
+ break;
+ }
api_incr_top(L);
lua_unlock(L);
}
@@ -567,20 +642,36 @@ LUA_API void lua_settable (lua_State *L, int idx) {
StkId t;
lua_lock(L);
api_checknelems(L, 2);
- t = luaA_index(L, idx);
+ t = index2adr(L, idx);
+ api_checkvalidindex(L, t);
luaV_settable(L, t, L->top - 2, L->top - 1);
L->top -= 2; /* pop index and value */
lua_unlock(L);
}
+LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
+ StkId t;
+ TValue key;
+ lua_lock(L);
+ api_checknelems(L, 1);
+ t = index2adr(L, idx);
+ api_checkvalidindex(L, t);
+ setsvalue(L, &key, luaS_new(L, k));
+ luaV_settable(L, t, &key, L->top - 1);
+ L->top--; /* pop value */
+ lua_unlock(L);
+}
+
+
LUA_API void lua_rawset (lua_State *L, int idx) {
StkId t;
lua_lock(L);
api_checknelems(L, 2);
- t = luaA_index(L, idx);
+ t = index2adr(L, idx);
api_check(L, ttistable(t));
- setobj2t(luaH_set(L, hvalue(t), L->top-2), L->top-1); /* write barrier */
+ setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1);
+ luaC_barriert(L, hvalue(t), L->top-1);
L->top -= 2;
lua_unlock(L);
}
@@ -590,54 +681,76 @@ LUA_API void lua_rawseti (lua_State *L, int idx, int n) {
StkId o;
lua_lock(L);
api_checknelems(L, 1);
- o = luaA_index(L, idx);
+ o = index2adr(L, idx);
api_check(L, ttistable(o));
- setobj2t(luaH_setnum(L, hvalue(o), n), L->top-1); /* write barrier */
+ setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);
+ luaC_barriert(L, hvalue(o), L->top-1);
L->top--;
lua_unlock(L);
}
LUA_API int lua_setmetatable (lua_State *L, int objindex) {
- TObject *obj, *mt;
- int res = 1;
+ TValue *obj;
+ Table *mt;
lua_lock(L);
api_checknelems(L, 1);
- obj = luaA_index(L, objindex);
- mt = (!ttisnil(L->top - 1)) ? L->top - 1 : defaultmeta(L);
- api_check(L, ttistable(mt));
+ obj = index2adr(L, objindex);
+ api_checkvalidindex(L, obj);
+ if (ttisnil(L->top - 1))
+ mt = NULL;
+ else {
+ api_check(L, ttistable(L->top - 1));
+ mt = hvalue(L->top - 1);
+ }
switch (ttype(obj)) {
case LUA_TTABLE: {
- hvalue(obj)->metatable = hvalue(mt); /* write barrier */
+ hvalue(obj)->metatable = mt;
+ if (mt)
+ luaC_objbarriert(L, hvalue(obj), mt);
break;
}
case LUA_TUSERDATA: {
- uvalue(obj)->uv.metatable = hvalue(mt); /* write barrier */
+ uvalue(obj)->metatable = mt;
+ if (mt)
+ luaC_objbarrier(L, rawuvalue(obj), mt);
break;
}
default: {
- res = 0; /* cannot set */
+ G(L)->mt[ttype(obj)] = mt;
break;
}
}
L->top--;
lua_unlock(L);
- return res;
+ return 1;
}
LUA_API int lua_setfenv (lua_State *L, int idx) {
StkId o;
- int res = 0;
+ int res = 1;
lua_lock(L);
api_checknelems(L, 1);
- o = luaA_index(L, idx);
- L->top--;
- api_check(L, ttistable(L->top));
- if (isLfunction(o)) {
- res = 1;
- clvalue(o)->l.g = *(L->top);
+ o = index2adr(L, idx);
+ api_checkvalidindex(L, o);
+ api_check(L, ttistable(L->top - 1));
+ switch (ttype(o)) {
+ case LUA_TFUNCTION:
+ clvalue(o)->c.env = hvalue(L->top - 1);
+ break;
+ case LUA_TUSERDATA:
+ uvalue(o)->env = hvalue(L->top - 1);
+ break;
+ case LUA_TTHREAD:
+ sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1));
+ break;
+ default:
+ res = 0;
+ break;
}
+ luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1));
+ L->top--;
lua_unlock(L);
return res;
}
@@ -647,12 +760,23 @@ LUA_API int lua_setfenv (lua_State *L, int idx) {
** `load' and `call' functions (run Lua code)
*/
+
+#define adjustresults(L,nres) \
+ { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; }
+
+
+#define checkresults(L,na,nr) \
+ api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)))
+
+
LUA_API void lua_call (lua_State *L, int nargs, int nresults) {
StkId func;
lua_lock(L);
api_checknelems(L, nargs+1);
+ checkresults(L, nargs, nresults);
func = L->top - (nargs+1);
luaD_call(L, func, nresults);
+ adjustresults(L, nresults);
lua_unlock(L);
}
@@ -679,10 +803,19 @@ LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) {
int status;
ptrdiff_t func;
lua_lock(L);
- func = (errfunc == 0) ? 0 : savestack(L, luaA_index(L, errfunc));
+ api_checknelems(L, nargs+1);
+ checkresults(L, nargs, nresults);
+ if (errfunc == 0)
+ func = 0;
+ else {
+ StkId o = index2adr(L, errfunc);
+ api_checkvalidindex(L, o);
+ func = savestack(L, o);
+ }
c.func = L->top - (nargs+1); /* function to be called */
c.nresults = nresults;
status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);
+ adjustresults(L, nresults);
lua_unlock(L);
return status;
}
@@ -700,12 +833,12 @@ struct CCallS { /* data to `f_Ccall' */
static void f_Ccall (lua_State *L, void *ud) {
struct CCallS *c = cast(struct CCallS *, ud);
Closure *cl;
- cl = luaF_newCclosure(L, 0);
+ cl = luaF_newCclosure(L, 0, getcurrenv(L));
cl->c.f = c->func;
- setclvalue(L->top, cl); /* push function */
- incr_top(L);
+ setclvalue(L, L->top, cl); /* push function */
+ api_incr_top(L);
setpvalue(L->top, c->ud); /* push only argument */
- incr_top(L);
+ api_incr_top(L);
luaD_call(L, L->top - 2, 0);
}
@@ -722,72 +855,98 @@ LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) {
}
-LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *data,
+LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
const char *chunkname) {
ZIO z;
int status;
- int c;
lua_lock(L);
if (!chunkname) chunkname = "?";
- luaZ_init(&z, reader, data, chunkname);
- c = luaZ_lookahead(&z);
- status = luaD_protectedparser(L, &z, (c == LUA_SIGNATURE[0]));
+ luaZ_init(L, &z, reader, data);
+ status = luaD_protectedparser(L, &z, chunkname);
lua_unlock(L);
return status;
}
-LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data) {
+LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) {
int status;
- TObject *o;
+ TValue *o;
lua_lock(L);
api_checknelems(L, 1);
o = L->top - 1;
- if (isLfunction(o) && clvalue(o)->l.nupvalues == 0) {
- luaU_dump(L, clvalue(o)->l.p, writer, data);
- status = 1;
- }
+ if (isLfunction(o))
+ status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0);
else
- status = 0;
+ status = 1;
lua_unlock(L);
return status;
}
-/*
-** Garbage-collection functions
-*/
+LUA_API int lua_status (lua_State *L) {
+ return L->status;
+}
-/* GC values are expressed in Kbytes: #bytes/2^10 */
-#define GCscalel(x) ((x)>>10)
-#define GCscale(x) (cast(int, GCscalel(x)))
-#define GCunscale(x) (cast(lu_mem, x)<<10)
-LUA_API int lua_getgcthreshold (lua_State *L) {
- int threshold;
- lua_lock(L);
- threshold = GCscale(G(L)->GCthreshold);
- lua_unlock(L);
- return threshold;
-}
+/*
+** Garbage-collection function
+*/
-LUA_API int lua_getgccount (lua_State *L) {
- int count;
+LUA_API int lua_gc (lua_State *L, int what, int data) {
+ int res = 0;
+ global_State *g;
lua_lock(L);
- count = GCscale(G(L)->nblocks);
+ g = G(L);
+ switch (what) {
+ case LUA_GCSTOP: {
+ g->GCthreshold = MAX_LUMEM;
+ break;
+ }
+ case LUA_GCRESTART: {
+ g->GCthreshold = g->totalbytes;
+ break;
+ }
+ case LUA_GCCOLLECT: {
+ luaC_fullgc(L);
+ break;
+ }
+ case LUA_GCCOUNT: {
+ /* GC values are expressed in Kbytes: #bytes/2^10 */
+ res = cast_int(g->totalbytes >> 10);
+ break;
+ }
+ case LUA_GCCOUNTB: {
+ res = cast_int(g->totalbytes & 0x3ff);
+ break;
+ }
+ case LUA_GCSTEP: {
+ lu_mem a = (cast(lu_mem, data) << 10);
+ if (a <= g->totalbytes)
+ g->GCthreshold = g->totalbytes - a;
+ else
+ g->GCthreshold = 0;
+ while (g->GCthreshold <= g->totalbytes)
+ luaC_step(L);
+ if (g->gcstate == GCSpause) /* end of cycle? */
+ res = 1; /* signal it */
+ break;
+ }
+ case LUA_GCSETPAUSE: {
+ res = g->gcpause;
+ g->gcpause = data;
+ break;
+ }
+ case LUA_GCSETSTEPMUL: {
+ res = g->gcstepmul;
+ g->gcstepmul = data;
+ break;
+ }
+ default: res = -1; /* invalid option */
+ }
lua_unlock(L);
- return count;
+ return res;
}
-LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) {
- lua_lock(L);
- if (cast(lu_mem, newthreshold) > GCscalel(MAX_LUMEM))
- G(L)->GCthreshold = MAX_LUMEM;
- else
- G(L)->GCthreshold = GCunscale(newthreshold);
- luaC_checkGC(L);
- lua_unlock(L);
-}
/*
@@ -795,11 +954,6 @@ LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) {
*/
-LUA_API const char *lua_version (void) {
- return LUA_VERSION;
-}
-
-
LUA_API int lua_error (lua_State *L) {
lua_lock(L);
api_checknelems(L, 1);
@@ -813,7 +967,7 @@ LUA_API int lua_next (lua_State *L, int idx) {
StkId t;
int more;
lua_lock(L);
- t = luaA_index(L, idx);
+ t = index2adr(L, idx);
api_check(L, ttistable(t));
more = luaH_next(L, hvalue(t), L->top - 1);
if (more) {
@@ -828,14 +982,14 @@ LUA_API int lua_next (lua_State *L, int idx) {
LUA_API void lua_concat (lua_State *L, int n) {
lua_lock(L);
- luaC_checkGC(L);
api_checknelems(L, n);
if (n >= 2) {
- luaV_concat(L, n, L->top - L->base - 1);
+ luaC_checkGC(L);
+ luaV_concat(L, n, cast_int(L->top - L->base) - 1);
L->top -= (n-1);
}
else if (n == 0) { /* push empty string */
- setsvalue2s(L->top, luaS_newlstr(L, NULL, 0));
+ setsvalue2s(L, L->top, luaS_newlstr(L, "", 0));
api_incr_top(L);
}
/* else n == 1; nothing to do */
@@ -843,39 +997,40 @@ LUA_API void lua_concat (lua_State *L, int n) {
}
+LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) {
+ lua_Alloc f;
+ lua_lock(L);
+ if (ud) *ud = G(L)->ud;
+ f = G(L)->frealloc;
+ lua_unlock(L);
+ return f;
+}
+
+
+LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) {
+ lua_lock(L);
+ G(L)->ud = ud;
+ G(L)->frealloc = f;
+ lua_unlock(L);
+}
+
+
LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
Udata *u;
lua_lock(L);
luaC_checkGC(L);
- u = luaS_newudata(L, size);
- setuvalue(L->top, u);
+ u = luaS_newudata(L, size, getcurrenv(L));
+ setuvalue(L, L->top, u);
api_incr_top(L);
lua_unlock(L);
return u + 1;
}
-LUA_API int lua_pushupvalues (lua_State *L) {
- Closure *func;
- int n, i;
- lua_lock(L);
- api_check(L, iscfunction(L->base - 1));
- func = clvalue(L->base - 1);
- n = func->c.nupvalues;
- luaD_checkstack(L, n + LUA_MINSTACK);
- for (i=0; i<n; i++) {
- setobj2s(L->top, &func->c.upvalue[i]);
- L->top++;
- }
- lua_unlock(L);
- return n;
-}
-static const char *aux_upvalue (lua_State *L, int funcindex, int n,
- TObject **val) {
+static const char *aux_upvalue (StkId fi, int n, TValue **val) {
Closure *f;
- StkId fi = luaA_index(L, funcindex);
if (!ttisfunction(fi)) return NULL;
f = clvalue(fi);
if (f->c.isC) {
@@ -894,11 +1049,11 @@ static const char *aux_upvalue (lua_State *L, int funcindex, int n,
LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {
const char *name;
- TObject *val;
+ TValue *val;
lua_lock(L);
- name = aux_upvalue(L, funcindex, n, &val);
+ name = aux_upvalue(index2adr(L, funcindex), n, &val);
if (name) {
- setobj2s(L->top, val);
+ setobj2s(L, L->top, val);
api_incr_top(L);
}
lua_unlock(L);
@@ -908,13 +1063,16 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {
LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
const char *name;
- TObject *val;
+ TValue *val;
+ StkId fi;
lua_lock(L);
+ fi = index2adr(L, funcindex);
api_checknelems(L, 1);
- name = aux_upvalue(L, funcindex, n, &val);
+ name = aux_upvalue(fi, n, &val);
if (name) {
L->top--;
- setobj(val, L->top); /* write barrier */
+ setobj(L, val, L->top);
+ luaC_barrier(L, clvalue(fi), L->top);
}
lua_unlock(L);
return name;
diff --git a/lib/lua/src/lcode.c b/lib/lua/src/lcode.c
index f393e7c..acc7851 100644
--- a/lib/lua/src/lcode.c
+++ b/lib/lua/src/lcode.c
@@ -1,5 +1,5 @@
/*
-** $Id: lcode.c,v 1.5 2007-07-25 16:54:32 pixel Exp $
+** $Id: lcode.c,v 1.6 2007-07-27 10:05:53 pixel Exp $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
@@ -8,12 +8,14 @@
#include <stdlib.h>
#define lcode_c
+#define LUA_CORE
#include "lua.h"
#include "lcode.h"
#include "ldebug.h"
#include "ldo.h"
+#include "lgc.h"
#include "llex.h"
#include "lmem.h"
#include "lobject.h"
@@ -25,16 +27,29 @@
#define hasjumps(e) ((e)->t != (e)->f)
+static int isnumeral(expdesc *e) {
+ return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
+}
+
+
void luaK_nil (FuncState *fs, int from, int n) {
Instruction *previous;
- if (fs->pc > fs->lasttarget && /* no jumps to current position? */
- GET_OPCODE(*(previous = &fs->f->code[fs->pc-1])) == OP_LOADNIL) {
- int pfrom = GETARG_A(*previous);
- int pto = GETARG_B(*previous);
- if (pfrom <= from && from <= pto+1) { /* can connect both? */
- if (from+n-1 > pto)
- SETARG_B(*previous, from+n-1);
- return;
+ if (fs->pc > fs->lasttarget) { /* no jumps to current position? */
+ if (fs->pc == 0) { /* function start? */
+ if (from >= fs->nactvar)
+ return; /* positions are already clean */
+ }
+ else {
+ previous = &fs->f->code[fs->pc-1];
+ if (GET_OPCODE(*previous) == OP_LOADNIL) {
+ int pfrom = GETARG_A(*previous);
+ int pto = GETARG_B(*previous);
+ if (pfrom <= from && from <= pto+1) { /* can connect both? */
+ if (from+n-1 > pto)
+ SETARG_B(*previous, from+n-1);
+ return;
+ }
+ }
}
}
luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */
@@ -51,13 +66,18 @@ int luaK_jump (FuncState *fs) {
}
-static int luaK_condjump (FuncState *fs, OpCode op, int A, int B, int C) {
+void luaK_ret (FuncState *fs, int first, int nret) {
+ luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);
+}
+
+
+static int condjump (FuncState *fs, OpCode op, int A, int B, int C) {
luaK_codeABC(fs, op, A, B, C);
return luaK_jump(fs);
}
-static void luaK_fixjump (FuncState *fs, int pc, int dest) {
+static void fixjump (FuncState *fs, int pc, int dest) {
Instruction *jmp = &fs->f->code[pc];
int offset = dest-(pc+1);
lua_assert(dest != NO_JUMP);
@@ -77,7 +97,7 @@ int luaK_getlabel (FuncState *fs) {
}
-static int luaK_getjump (FuncState *fs, int pc) {
+static int getjump (FuncState *fs, int pc) {
int offset = GETARG_sBx(fs->f->code[pc]);
if (offset == NO_JUMP) /* point to itself represents end of list */
return NO_JUMP; /* end of list */
@@ -88,7 +108,7 @@ static int luaK_getjump (FuncState *fs, int pc) {
static Instruction *getjumpcontrol (FuncState *fs, int pc) {
Instruction *pi = &fs->f->code[pc];
- if (pc >= 1 && testOpMode(GET_OPCODE(*(pi-1)), OpModeT))
+ if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1))))
return pi-1;
else
return pi;
@@ -99,51 +119,49 @@ static Instruction *getjumpcontrol (FuncState *fs, int pc) {
** check whether list has any jump that do not produce a value
** (or produce an inverted value)
*/
-static int need_value (FuncState *fs, int list, int cond) {
- for (; list != NO_JUMP; list = luaK_getjump(fs, list)) {
+static int need_value (FuncState *fs, int list) {
+ for (; list != NO_JUMP; list = getjump(fs, list)) {
Instruction i = *getjumpcontrol(fs, list);
- if (GET_OPCODE(i) != OP_TEST ||
- GETARG_A(i) != NO_REG ||
- GETARG_C(i) != cond)
- return 1;
+ if (GET_OPCODE(i) != OP_TESTSET) return 1;
}
return 0; /* not found */
}
-static void patchtestreg (Instruction *i, int reg) {
- if (reg == NO_REG) reg = GETARG_B(*i);
- SETARG_A(*i, reg);
+static int patchtestreg (FuncState *fs, int node, int reg) {
+ Instruction *i = getjumpcontrol(fs, node);
+ if (GET_OPCODE(*i) != OP_TESTSET)
+ return 0; /* cannot patch other instructions */
+ if (reg != NO_REG && reg != GETARG_B(*i))
+ SETARG_A(*i, reg);
+ else /* no register to put value or register already has the value */
+ *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));
+
+ return 1;
}
static void removevalues (FuncState *fs, int list) {
- for (; list != NO_JUMP; list = luaK_getjump(fs, list)) {
- Instruction *i = getjumpcontrol(fs, list);
- if (GET_OPCODE(*i) == OP_TEST)
- patchtestreg(i, NO_REG);
- }
+ for (; list != NO_JUMP; list = getjump(fs, list))
+ patchtestreg(fs, list, NO_REG);
}
-static void luaK_patchlistaux (FuncState *fs, int list, int vtarget, int reg,
- int dtarget) {
+static void patchlistaux (FuncState *fs, int list, int vtarget, int reg,
+ int dtarget) {
while (list != NO_JUMP) {
- int next = luaK_getjump(fs, list);
- Instruction *i = getjumpcontrol(fs, list);
- if (GET_OPCODE(*i) == OP_TEST && GETARG_A(*i) == NO_REG) {
- patchtestreg(i, reg);
- luaK_fixjump(fs, list, vtarget);
- }
+ int next = getjump(fs, list);
+ if (patchtestreg(fs, list, reg))
+ fixjump(fs, list, vtarget);
else
- luaK_fixjump(fs, list, dtarget); /* jump to default target */
+ fixjump(fs, list, dtarget); /* jump to default target */
list = next;
}
}
-static void luaK_dischargejpc (FuncState *fs) {
- luaK_patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc);
+static void dischargejpc (FuncState *fs) {
+ patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc);
fs->jpc = NO_JUMP;
}
@@ -153,7 +171,7 @@ void luaK_patchlist (FuncState *fs, int list, int target) {
luaK_patchtohere(fs, list);
else {
lua_assert(target < fs->pc);
- luaK_patchlistaux(fs, list, target, NO_REG, target);
+ patchlistaux(fs, list, target, NO_REG, target);
}
}
@@ -171,9 +189,9 @@ void luaK_concat (FuncState *fs, int *l1, int l2) {
else {
int list = *l1;
int next;
- while ((next = luaK_getjump(fs, list)) != NO_JUMP) /* find last element */
+ while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */
list = next;
- luaK_fixjump(fs, list, l2);
+ fixjump(fs, list, l2);
}
}
@@ -183,7 +201,7 @@ void luaK_checkstack (FuncState *fs, int n) {
if (newstack > fs->f->maxstacksize) {
if (newstack >= MAXSTACK)
luaX_syntaxerror(fs->ls, "function or expression too complex");
- fs->f->maxstacksize = cast(lu_byte, newstack);
+ fs->f->maxstacksize = cast_byte(newstack);
}
}
@@ -195,7 +213,7 @@ void luaK_reserveregs (FuncState *fs, int n) {
static void freereg (FuncState *fs, int reg) {
- if (reg >= fs->nactvar && reg < MAXSTACK) {
+ if (!ISK(reg) && reg >= fs->nactvar) {
fs->freereg--;
lua_assert(reg == fs->freereg);
}
@@ -204,56 +222,81 @@ static void freereg (FuncState *fs, int reg) {
static void freeexp (FuncState *fs, expdesc *e) {
if (e->k == VNONRELOC)
- freereg(fs, e->info);
+ freereg(fs, e->u.s.info);
}
-static int addk (FuncState *fs, TObject *k, TObject *v) {
- const TObject *idx = luaH_get(fs->h, k);
+static int addk (FuncState *fs, TValue *k, TValue *v) {
+ lua_State *L = fs->L;
+ TValue *idx = luaH_set(L, fs->h, k);
+ Proto *f = fs->f;
+ int oldsize = f->sizek;
if (ttisnumber(idx)) {
- lua_assert(luaO_rawequalObj(&fs->f->k[cast(int, nvalue(idx))], v));
- return cast(int, nvalue(idx));
+ lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v));
+ return cast_int(nvalue(idx));
}
else { /* constant not found; create a new entry */
- Proto *f = fs->f;
- luaM_growvector(fs->L, f->k, fs->nk, f->sizek, TObject,
+ setnvalue(idx, cast_num(fs->nk));
+ luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,
MAXARG_Bx, "constant table overflow");
- setobj2n(&f->k[fs->nk], v);
- setnvalue(luaH_set(fs->L, fs->h, k), cast(lua_Number, fs->nk));
+ while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
+ setobj(L, &f->k[fs->nk], v);
+ luaC_barrier(L, f, v);
return fs->nk++;
}
}
int luaK_stringK (FuncState *fs, TString *s) {
- TObject o;
- setsvalue(&o, s);
+ TValue o;
+ setsvalue(fs->L, &o, s);
return addk(fs, &o, &o);
}
int luaK_numberK (FuncState *fs, lua_Number r) {
- TObject o;
+ TValue o;
setnvalue(&o, r);
return addk(fs, &o, &o);
}
-static int nil_constant (FuncState *fs) {
- TObject k, v;
+static int boolK (FuncState *fs, int b) {
+ TValue o;
+ setbvalue(&o, b);
+ return addk(fs, &o, &o);
+}
+
+
+static int nilK (FuncState *fs) {
+ TValue k, v;
setnilvalue(&v);
- sethvalue(&k, fs->h); /* cannot use nil as key; instead use table itself */
+ /* cannot use nil as key; instead use table itself to represent nil */
+ sethvalue(fs->L, &k, fs->h);
return addk(fs, &k, &v);
}
-void luaK_setcallreturns (FuncState *fs, expdesc *e, int nresults) {
+void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
if (e->k == VCALL) { /* expression is an open function call? */
SETARG_C(getcode(fs, e), nresults+1);
- if (nresults == 1) { /* `regular' expression? */
- e->k = VNONRELOC;
- e->info = GETARG_A(getcode(fs, e));
- }
+ }
+ else if (e->k == VVARARG) {
+ SETARG_B(getcode(fs, e), nresults+1);
+ SETARG_A(getcode(fs, e), fs->freereg);
+ luaK_reserveregs(fs, 1);
+ }
+}
+
+
+void luaK_setoneret (FuncState *fs, expdesc *e) {
+ if (e->k == VCALL) { /* expression is an open function call? */
+ e->k = VNONRELOC;
+ e->u.s.info = GETARG_A(getcode(fs, e));
+ }
+ else if (e->k == VVARARG) {
+ SETARG_B(getcode(fs, e), 2);
+ e->k = VRELOCABLE; /* can relocate its simple result */
}
}
@@ -265,24 +308,25 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
break;
}
case VUPVAL: {
- e->info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->info, 0);
+ e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0);
e->k = VRELOCABLE;
break;
}
case VGLOBAL: {
- e->info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->info);
+ e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info);
e->k = VRELOCABLE;
break;
}
case VINDEXED: {
- freereg(fs, e->aux);
- freereg(fs, e->info);
- e->info = luaK_codeABC(fs, OP_GETTABLE, 0, e->info, e->aux);
+ freereg(fs, e->u.s.aux);
+ freereg(fs, e->u.s.info);
+ e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux);
e->k = VRELOCABLE;
break;
}
+ case VVARARG:
case VCALL: {
- luaK_setcallreturns(fs, e, 1);
+ luaK_setoneret(fs, e);
break;
}
default: break; /* there is one value available (somewhere) */
@@ -308,7 +352,11 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
break;
}
case VK: {
- luaK_codeABx(fs, OP_LOADK, reg, e->info);
+ luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info);
+ break;
+ }
+ case VKNUM: {
+ luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));
break;
}
case VRELOCABLE: {
@@ -317,8 +365,8 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
break;
}
case VNONRELOC: {
- if (reg != e->info)
- luaK_codeABC(fs, OP_MOVE, reg, e->info, 0);
+ if (reg != e->u.s.info)
+ luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0);
break;
}
default: {
@@ -326,7 +374,7 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
return; /* nothing to do... */
}
}
- e->info = reg;
+ e->u.s.info = reg;
e->k = VNONRELOC;
}
@@ -339,28 +387,26 @@ static void discharge2anyreg (FuncState *fs, expdesc *e) {
}
-static void luaK_exp2reg (FuncState *fs, expdesc *e, int reg) {
+static void exp2reg (FuncState *fs, expdesc *e, int reg) {
discharge2reg(fs, e, reg);
if (e->k == VJMP)
- luaK_concat(fs, &e->t, e->info); /* put this jump in `t' list */
+ luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */
if (hasjumps(e)) {
int final; /* position after whole expression */
int p_f = NO_JUMP; /* position of an eventual LOAD false */
int p_t = NO_JUMP; /* position of an eventual LOAD true */
- if (need_value(fs, e->t, 1) || need_value(fs, e->f, 0)) {
- int fj = NO_JUMP; /* first jump (over LOAD ops.) */
- if (e->k != VJMP)
- fj = luaK_jump(fs);
+ if (need_value(fs, e->t) || need_value(fs, e->f)) {
+ int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs);
p_f = code_label(fs, reg, 0, 1);
p_t = code_label(fs, reg, 1, 0);
luaK_patchtohere(fs, fj);
}
final = luaK_getlabel(fs);
- luaK_patchlistaux(fs, e->f, final, reg, p_f);
- luaK_patchlistaux(fs, e->t, final, reg, p_t);
+ patchlistaux(fs, e->f, final, reg, p_f);
+ patchlistaux(fs, e->t, final, reg, p_t);
}
e->f = e->t = NO_JUMP;
- e->info = reg;
+ e->u.s.info = reg;
e->k = VNONRELOC;
}
@@ -369,21 +415,21 @@ void luaK_exp2nextreg (FuncState *fs, expdesc *e) {
luaK_dischargevars(fs, e);
freeexp(fs, e);
luaK_reserveregs(fs, 1);
- luaK_exp2reg(fs, e, fs->freereg - 1);
+ exp2reg(fs, e, fs->freereg - 1);
}
int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
luaK_dischargevars(fs, e);
if (e->k == VNONRELOC) {
- if (!hasjumps(e)) return e->info; /* exp is already in a register */
- if (e->info >= fs->nactvar) { /* reg. is not a local? */
- luaK_exp2reg(fs, e, e->info); /* put value on it */
- return e->info;
+ if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */
+ if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */
+ exp2reg(fs, e, e->u.s.info); /* put value on it */
+ return e->u.s.info;
}
}
luaK_exp2nextreg(fs, e); /* default */
- return e->info;
+ return e->u.s.info;
}
@@ -398,17 +444,22 @@ void luaK_exp2val (FuncState *fs, expdesc *e) {
int luaK_exp2RK (FuncState *fs, expdesc *e) {
luaK_exp2val(fs, e);
switch (e->k) {
+ case VKNUM:
+ case VTRUE:
+ case VFALSE:
case VNIL: {
- if (fs->nk + MAXSTACK <= MAXARG_C) { /* constant fit in argC? */
- e->info = nil_constant(fs);
+ if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */
+ e->u.s.info = (e->k == VNIL) ? nilK(fs) :
+ (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :
+ boolK(fs, (e->k == VTRUE));
e->k = VK;
- return e->info + MAXSTACK;
+ return RKASK(e->u.s.info);
}
else break;
}
case VK: {
- if (e->info + MAXSTACK <= MAXARG_C) /* constant fit in argC? */
- return e->info + MAXSTACK;
+ if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */
+ return RKASK(e->u.s.info);
else break;
}
default: break;
@@ -418,26 +469,26 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) {
}
-void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) {
+void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
switch (var->k) {
case VLOCAL: {
- freeexp(fs, exp);
- luaK_exp2reg(fs, exp, var->info);
+ freeexp(fs, ex);
+ exp2reg(fs, ex, var->u.s.info);
return;
}
case VUPVAL: {
- int e = luaK_exp2anyreg(fs, exp);
- luaK_codeABC(fs, OP_SETUPVAL, e, var->info, 0);
+ int e = luaK_exp2anyreg(fs, ex);
+ luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0);
break;
}
case VGLOBAL: {
- int e = luaK_exp2anyreg(fs, exp);
- luaK_codeABx(fs, OP_SETGLOBAL, e, var->info);
+ int e = luaK_exp2anyreg(fs, ex);
+ luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info);
break;
}
case VINDEXED: {
- int e = luaK_exp2RK(fs, exp);
- luaK_codeABC(fs, OP_SETTABLE, var->info, var->aux, e);
+ int e = luaK_exp2RK(fs, ex);
+ luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e);
break;
}
default: {
@@ -445,7 +496,7 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) {
break;
}
}
- freeexp(fs, exp);
+ freeexp(fs, ex);
}
@@ -455,17 +506,17 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
freeexp(fs, e);
func = fs->freereg;
luaK_reserveregs(fs, 2);
- luaK_codeABC(fs, OP_SELF, func, e->info, luaK_exp2RK(fs, key));
+ luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key));
freeexp(fs, key);
- e->info = func;
+ e->u.s.info = func;
e->k = VNONRELOC;
}
static void invertjump (FuncState *fs, expdesc *e) {
- Instruction *pc = getjumpcontrol(fs, e->info);
- lua_assert(testOpMode(GET_OPCODE(*pc), OpModeT) &&
- GET_OPCODE(*pc) != OP_TEST);
+ Instruction *pc = getjumpcontrol(fs, e->u.s.info);
+ lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&
+ GET_OPCODE(*pc) != OP_TEST);
SETARG_A(*pc, !(GETARG_A(*pc)));
}
@@ -475,13 +526,13 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) {
Instruction ie = getcode(fs, e);
if (GET_OPCODE(ie) == OP_NOT) {
fs->pc--; /* remove previous OP_NOT */
- return luaK_condjump(fs, OP_TEST, GETARG_B(ie), GETARG_B(ie), !cond);
+ return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);
}
/* else go through */
}
discharge2anyreg(fs, e);
freeexp(fs, e);
- return luaK_condjump(fs, OP_TEST, NO_REG, e->info, cond);
+ return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond);
}
@@ -489,7 +540,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) {
int pc; /* pc of last jump */
luaK_dischargevars(fs, e);
switch (e->k) {
- case VK: case VTRUE: {
+ case VK: case VKNUM: case VTRUE: {
pc = NO_JUMP; /* always true; do nothing */
break;
}
@@ -499,7 +550,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) {
}
case VJMP: {
invertjump(fs, e);
- pc = e->info;
+ pc = e->u.s.info;
break;
}
default: {
@@ -508,10 +559,12 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) {
}
}
luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */
+ luaK_patchtohere(fs, e->t);
+ e->t = NO_JUMP;
}
-void luaK_goiffalse (FuncState *fs, expdesc *e) {
+static void luaK_goiffalse (FuncState *fs, expdesc *e) {
int pc; /* pc of last jump */
luaK_dischargevars(fs, e);
switch (e->k) {
@@ -524,7 +577,7 @@ void luaK_goiffalse (FuncState *fs, expdesc *e) {
break;
}
case VJMP: {
- pc = e->info;
+ pc = e->u.s.info;
break;
}
default: {
@@ -533,6 +586,8 @@ void luaK_goiffalse (FuncState *fs, expdesc *e) {
}
}
luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */
+ luaK_patchtohere(fs, e->f);
+ e->f = NO_JUMP;
}
@@ -543,7 +598,7 @@ static void codenot (FuncState *fs, expdesc *e) {
e->k = VTRUE;
break;
}
- case VK: case VTRUE: {
+ case VK: case VKNUM: case VTRUE: {
e->k = VFALSE;
break;
}
@@ -555,7 +610,7 @@ static void codenot (FuncState *fs, expdesc *e) {
case VNONRELOC: {
discharge2anyreg(fs, e);
freeexp(fs, e);
- e->info = luaK_codeABC(fs, OP_NOT, 0, e->info, 0);
+ e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0);
e->k = VRELOCABLE;
break;
}
@@ -572,25 +627,91 @@ static void codenot (FuncState *fs, expdesc *e) {
void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
- t->aux = luaK_exp2RK(fs, k);
+ t->u.s.aux = luaK_exp2RK(fs, k);
t->k = VINDEXED;
}
-void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
- if (op == OPR_MINUS) {
- luaK_exp2val(fs, e);
- if (e->k == VK && ttisnumber(&fs->f->k[e->info]))
- e->info = luaK_numberK(fs, -nvalue(&fs->f->k[e->info]));
+static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
+ lua_Number v1, v2, r;
+ if (!isnumeral(e1) || !isnumeral(e2)) return 0;
+ v1 = e1->u.nval;
+ v2 = e2->u.nval;
+ switch (op) {
+ case OP_ADD: r = luai_numadd(v1, v2); break;
+ case OP_SUB: r = luai_numsub(v1, v2); break;
+ case OP_MUL: r = luai_nummul(v1, v2); break;
+ case OP_DIV:
+ if (v2 == 0) return 0; /* do not attempt to divide by 0 */
+ r = luai_numdiv(v1, v2); break;
+ case OP_MOD:
+ if (v2 == 0) return 0; /* do not attempt to divide by 0 */
+ r = luai_nummod(v1, v2); break;
+ case OP_POW: r = luai_numpow(v1, v2); break;
+ case OP_UNM: r = luai_numunm(v1); break;
+ case OP_LEN: return 0; /* no constant folding for 'len' */
+ default: lua_assert(0); r = 0; break;
+ }
+ if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */
+ e1->u.nval = r;
+ return 1;
+}
+
+
+static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {
+ if (constfolding(op, e1, e2))
+ return;
+ else {
+ int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;
+ int o1 = luaK_exp2RK(fs, e1);
+ if (o1 > o2) {
+ freeexp(fs, e1);
+ freeexp(fs, e2);
+ }
else {
- luaK_exp2anyreg(fs, e);
- freeexp(fs, e);
- e->info = luaK_codeABC(fs, OP_UNM, 0, e->info, 0);
- e->k = VRELOCABLE;
+ freeexp(fs, e2);
+ freeexp(fs, e1);
}
+ e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2);
+ e1->k = VRELOCABLE;
+ }
+}
+
+
+static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,
+ expdesc *e2) {
+ int o1 = luaK_exp2RK(fs, e1);
+ int o2 = luaK_exp2RK(fs, e2);
+ freeexp(fs, e2);
+ freeexp(fs, e1);
+ if (cond == 0 && op != OP_EQ) {
+ int temp; /* exchange args to replace by `<' or `<=' */
+ temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */
+ cond = 1;
+ }
+ e1->u.s.info = condjump(fs, op, cond, o1, o2);
+ e1->k = VJMP;
+}
+
+
+void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
+ expdesc e2;
+ e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
+ switch (op) {
+ case OPR_MINUS: {
+ if (e->k == VK)
+ luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */
+ codearith(fs, OP_UNM, e, &e2);
+ break;
+ }
+ case OPR_NOT: codenot(fs, e); break;
+ case OPR_LEN: {
+ luaK_exp2anyreg(fs, e); /* cannot operate on constants */
+ codearith(fs, OP_LEN, e, &e2);
+ break;
+ }
+ default: lua_assert(0);
}
- else /* op == NOT */
- codenot(fs, e);
}
@@ -598,20 +719,21 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
switch (op) {
case OPR_AND: {
luaK_goiftrue(fs, v);
- luaK_patchtohere(fs, v->t);
- v->t = NO_JUMP;
break;
}
case OPR_OR: {
luaK_goiffalse(fs, v);
- luaK_patchtohere(fs, v->f);
- v->f = NO_JUMP;
break;
}
case OPR_CONCAT: {
luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */
break;
}
+ case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
+ case OPR_MOD: case OPR_POW: {
+ if (!isnumeral(v)) luaK_exp2RK(fs, v);
+ break;
+ }
default: {
luaK_exp2RK(fs, v);
break;
@@ -620,67 +742,49 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
}
-static void codebinop (FuncState *fs, expdesc *res, BinOpr op,
- int o1, int o2) {
- if (op <= OPR_POW) { /* arithmetic operator? */
- OpCode opc = cast(OpCode, (op - OPR_ADD) + OP_ADD); /* ORDER OP */
- res->info = luaK_codeABC(fs, opc, 0, o1, o2);
- res->k = VRELOCABLE;
- }
- else { /* test operator */
- static const OpCode ops[] = {OP_EQ, OP_EQ, OP_LT, OP_LE, OP_LT, OP_LE};
- int cond = 1;
- if (op >= OPR_GT) { /* `>' or `>='? */
- int temp; /* exchange args and replace by `<' or `<=' */
- temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */
- }
- else if (op == OPR_NE) cond = 0;
- res->info = luaK_condjump(fs, ops[op - OPR_NE], cond, o1, o2);
- res->k = VJMP;
- }
-}
-
-
void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {
switch (op) {
case OPR_AND: {
lua_assert(e1->t == NO_JUMP); /* list must be closed */
luaK_dischargevars(fs, e2);
- luaK_concat(fs, &e1->f, e2->f);
- e1->k = e2->k; e1->info = e2->info; e1->aux = e2->aux; e1->t = e2->t;
+ luaK_concat(fs, &e2->f, e1->f);
+ *e1 = *e2;
break;
}
case OPR_OR: {
lua_assert(e1->f == NO_JUMP); /* list must be closed */
luaK_dischargevars(fs, e2);
- luaK_concat(fs, &e1->t, e2->t);
- e1->k = e2->k; e1->info = e2->info; e1->aux = e2->aux; e1->f = e2->f;
+ luaK_concat(fs, &e2->t, e1->t);
+ *e1 = *e2;
break;
}
case OPR_CONCAT: {
luaK_exp2val(fs, e2);
if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {
- lua_assert(e1->info == GETARG_B(getcode(fs, e2))-1);
+ lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1);
freeexp(fs, e1);
- SETARG_B(getcode(fs, e2), e1->info);
- e1->k = e2->k; e1->info = e2->info;
+ SETARG_B(getcode(fs, e2), e1->u.s.info);
+ e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info;
}
else {
- luaK_exp2nextreg(fs, e2);
- freeexp(fs, e2);
- freeexp(fs, e1);
- e1->info = luaK_codeABC(fs, OP_CONCAT, 0, e1->info, e2->info);
- e1->k = VRELOCABLE;
+ luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */
+ codearith(fs, OP_CONCAT, e1, e2);
}
break;
}
- default: {
- int o1 = luaK_exp2RK(fs, e1);
- int o2 = luaK_exp2RK(fs, e2);
- freeexp(fs, e2);
- freeexp(fs, e1);
- codebinop(fs, e1, op, o1, o2);
- }
+ case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break;
+ case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break;
+ case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break;
+ case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break;
+ case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break;
+ case OPR_POW: codearith(fs, OP_POW, e1, e2); break;
+ case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break;
+ case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break;
+ case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break;
+ case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break;
+ case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break;
+ case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break;
+ default: lua_assert(0);
}
}
@@ -690,9 +794,9 @@ void luaK_fixline (FuncState *fs, int line) {
}
-int luaK_code (FuncState *fs, Instruction i, int line) {
+static int luaK_code (FuncState *fs, Instruction i, int line) {
Proto *f = fs->f;
- luaK_dischargejpc(fs); /* `pc' will change */
+ dischargejpc(fs); /* `pc' will change */
/* put new instruction in code array */
luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction,
MAX_INT, "code size overflow");
@@ -707,12 +811,29 @@ int luaK_code (FuncState *fs, Instruction i, int line) {
int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {
lua_assert(getOpMode(o) == iABC);
+ lua_assert(getBMode(o) != OpArgN || b == 0);
+ lua_assert(getCMode(o) != OpArgN || c == 0);
return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline);
}
int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);
+ lua_assert(getCMode(o) == OpArgN);
return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline);
}
+
+void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {
+ int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1;
+ int b = (tostore == LUA_MULTRET) ? 0 : tostore;
+ lua_assert(tostore != 0);
+ if (c <= MAXARG_C)
+ luaK_codeABC(fs, OP_SETLIST, base, b, c);
+ else {
+ luaK_codeABC(fs, OP_SETLIST, base, b, 0);
+ luaK_code(fs, cast(Instruction, c), fs->ls->lastline);
+ }
+ fs->freereg = base + 1; /* free registers with list values */
+}
+
diff --git a/lib/lua/src/ldebug.c b/lib/lua/src/ldebug.c
index 4f69bad..7d606c6 100644
--- a/lib/lua/src/ldebug.c
+++ b/lib/lua/src/ldebug.c
@@ -1,14 +1,17 @@
/*
-** $Id: ldebug.c,v 1.6 2006-02-09 16:59:55 pixel Exp $
+** $Id: ldebug.c,v 1.7 2007-07-27 10:05:53 pixel Exp $
** Debug Interface
** See Copyright Notice in lua.h
*/
-#include <stdlib.h>
+#include <stdarg.h>
+#include <stddef.h>
#include <string.h>
+
#define ldebug_c
+#define LUA_CORE
#include "lua.h"
@@ -27,23 +30,19 @@
-static const char *getfuncname (CallInfo *ci, const char **name);
-
+static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name);
-#define isLua(ci) (!((ci)->state & CI_C))
-
-static int currentpc (CallInfo *ci) {
+static int currentpc (lua_State *L, CallInfo *ci) {
if (!isLua(ci)) return -1; /* function is not a Lua function? */
- if (ci->state & CI_HASFRAME) /* function has a frame? */
- ci->u.l.savedpc = *ci->u.l.pc; /* use `pc' from there */
- /* function's pc is saved */
- return pcRel(ci->u.l.savedpc, ci_func(ci)->l.p);
+ if (ci == L->ci)
+ ci->savedpc = L->savedpc;
+ return pcRel(ci->savedpc, ci_func(ci)->l.p);
}
-static int currentline (CallInfo *ci) {
- int pc = currentpc(ci);
+static int currentline (lua_State *L, CallInfo *ci) {
+ int pc = currentpc(L, ci);
if (pc < 0)
return -1; /* only active lua functions have current-line information */
else
@@ -51,14 +50,6 @@ static int currentline (CallInfo *ci) {
}
-void luaG_inithooks (lua_State *L) {
- CallInfo *ci;
- for (ci = L->ci; ci != L->base_ci; ci--) /* update all `savedpc's */
- currentpc(ci);
- L->hookinit = 1;
-}
-
-
/*
** this function can be called asynchronous (e.g. during a signal)
*/
@@ -70,8 +61,7 @@ LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
L->hook = func;
L->basehookcount = count;
resethookcount(L);
- L->hookmask = cast(lu_byte, mask);
- L->hookinit = 0;
+ L->hookmask = cast_byte(mask);
return 1;
}
@@ -127,18 +117,18 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
lua_lock(L);
for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) {
level--;
- if (!(ci->state & CI_C)) /* Lua function? */
- level -= ci->u.l.tailcalls; /* skip lost tail calls */
+ if (f_isLua(ci)) /* Lua function? */
+ level -= ci->tailcalls; /* skip lost tail calls */
}
- if (level > 0 || ci == L->base_ci) status = 0; /* there is no such level */
- else if (level < 0) { /* level is of a lost tail call */
+ if (level == 0 && ci > L->base_ci) { /* level found? */
status = 1;
- ar->i_ci = 0;
+ ar->i_ci = cast_int(ci - L->base_ci);
}
- else {
+ else if (level < 0) { /* level is of a lost tail call? */
status = 1;
- ar->i_ci = ci - L->base_ci;
+ ar->i_ci = 0;
}
+ else status = 0; /* no such level */
lua_unlock(L);
return status;
}
@@ -149,87 +139,94 @@ static Proto *getluaproto (CallInfo *ci) {
}
-LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
+static const char *findlocal (lua_State *L, CallInfo *ci, int n) {
const char *name;
- CallInfo *ci;
- Proto *fp;
- lua_lock(L);
- name = NULL;
- ci = L->base_ci + ar->i_ci;
- fp = getluaproto(ci);
- if (fp) { /* is a Lua function? */
- name = luaF_getlocalname(fp, n, currentpc(ci));
- if (name)
- luaA_pushobject(L, ci->base+(n-1)); /* push value */
+ Proto *fp = getluaproto(ci);
+ if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL)
+ return name; /* is a local variable in a Lua function */
+ else {
+ StkId limit = (ci == L->ci) ? L->top : (ci+1)->func;
+ if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */
+ return "(*temporary)";
+ else
+ return NULL;
}
+}
+
+
+LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
+ CallInfo *ci = L->base_ci + ar->i_ci;
+ const char *name = findlocal(L, ci, n);
+ lua_lock(L);
+ if (name)
+ luaA_pushobject(L, ci->base + (n - 1));
lua_unlock(L);
return name;
}
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
- const char *name;
- CallInfo *ci;
- Proto *fp;
+ CallInfo *ci = L->base_ci + ar->i_ci;
+ const char *name = findlocal(L, ci, n);
lua_lock(L);
- name = NULL;
- ci = L->base_ci + ar->i_ci;
- fp = getluaproto(ci);
- L->top--; /* pop new value */
- if (fp) { /* is a Lua function? */
- name = luaF_getlocalname(fp, n, currentpc(ci));
- if (!name || name[0] == '(') /* `(' starts private locals */
- name = NULL;
- else
- setobjs2s(ci->base+(n-1), L->top);
- }
+ if (name)
+ setobjs2s(L, ci->base + (n - 1), L->top - 1);
+ L->top--; /* pop value */
lua_unlock(L);
return name;
}
-static void funcinfo (lua_Debug *ar, StkId func) {
- Closure *cl = clvalue(func);
+static void funcinfo (lua_Debug *ar, Closure *cl) {
if (cl->c.isC) {
ar->source = "=[C]";
ar->linedefined = -1;
+ ar->lastlinedefined = -1;
ar->what = "C";
}
else {
ar->source = getstr(cl->l.p->source);
- ar->linedefined = cl->l.p->lineDefined;
+ ar->linedefined = cl->l.p->linedefined;
+ ar->lastlinedefined = cl->l.p->lastlinedefined;
ar->what = (ar->linedefined == 0) ? "main" : "Lua";
}
luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
}
-static const char *travglobals (lua_State *L, const TObject *o) {
- Table *g = hvalue(gt(L));
- int i = sizenode(g);
- while (i--) {
- Node *n = gnode(g, i);
- if (luaO_rawequalObj(o, gval(n)) && ttisstring(gkey(n)))
- return getstr(tsvalue(gkey(n)));
- }
- return NULL;
-}
-
-
-static void info_tailcall (lua_State *L, lua_Debug *ar) {
+static void info_tailcall (lua_Debug *ar) {
ar->name = ar->namewhat = "";
ar->what = "tail";
- ar->linedefined = ar->currentline = -1;
+ ar->lastlinedefined = ar->linedefined = ar->currentline = -1;
ar->source = "=(tail call)";
luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
ar->nups = 0;
- setnilvalue(L->top);
+}
+
+
+static void collectvalidlines (lua_State *L, Closure *f) {
+ if (f == NULL || f->c.isC) {
+ setnilvalue(L->top);
+ }
+ else {
+ Table *t = luaH_new(L, 0, 0);
+ int *lineinfo = f->l.p->lineinfo;
+ int i;
+ for (i=0; i<f->l.p->sizelineinfo; i++)
+ setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);
+ sethvalue(L, L->top, t);
+ }
+ incr_top(L);
}
static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
- StkId f, CallInfo *ci) {
+ Closure *f, CallInfo *ci) {
int status = 1;
+ if (f == NULL) {
+ info_tailcall(ar);
+ return status;
+ }
for (; *what; what++) {
switch (*what) {
case 'S': {
@@ -237,27 +234,24 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
break;
}
case 'l': {
- ar->currentline = (ci) ? currentline(ci) : -1;
+ ar->currentline = (ci) ? currentline(L, ci) : -1;
break;
}
case 'u': {
- ar->nups = clvalue(f)->c.nupvalues;
+ ar->nups = f->c.nupvalues;
break;
}
case 'n': {
- ar->namewhat = (ci) ? getfuncname(ci, &ar->name) : NULL;
+ ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL;
if (ar->namewhat == NULL) {
- /* try to find a global name */
- if ((ar->name = travglobals(L, f)) != NULL)
- ar->namewhat = "global";
- else ar->namewhat = ""; /* not found */
+ ar->namewhat = ""; /* not found */
+ ar->name = NULL;
}
break;
}
- case 'f': {
- setobj2s(L->top, f);
+ case 'L':
+ case 'f': /* handled by lua_getinfo */
break;
- }
default: status = 0; /* invalid option */
}
}
@@ -266,23 +260,30 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
- int status = 1;
+ int status;
+ Closure *f = NULL;
+ CallInfo *ci = NULL;
lua_lock(L);
if (*what == '>') {
- StkId f = L->top - 1;
- if (!ttisfunction(f))
- luaG_runerror(L, "value for `lua_getinfo' is not a function");
- status = auxgetinfo(L, what + 1, ar, f, NULL);
+ StkId func = L->top - 1;
+ luai_apicheck(L, ttisfunction(func));
+ what++; /* skip the '>' */
+ f = clvalue(func);
L->top--; /* pop function */
}
else if (ar->i_ci != 0) { /* no tail call? */
- CallInfo *ci = L->base_ci + ar->i_ci;
- lua_assert(ttisfunction(ci->base - 1));
- status = auxgetinfo(L, what, ar, ci->base - 1, ci);
+ ci = L->base_ci + ar->i_ci;
+ lua_assert(ttisfunction(ci->func));
+ f = clvalue(ci->func);
}
- else
- info_tailcall(L, ar);
- if (strchr(what, 'f')) incr_top(L);
+ status = auxgetinfo(L, what, ar, f, ci);
+ if (strchr(what, 'f')) {
+ if (f == NULL) setnilvalue(L->top);
+ else setclvalue(L, L->top, f);
+ incr_top(L);
+ }
+ if (strchr(what, 'L'))
+ collectvalidlines(L, f);
lua_unlock(L);
return status;
}
@@ -304,72 +305,89 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
static int precheck (const Proto *pt) {
check(pt->maxstacksize <= MAXSTACK);
+ lua_assert(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize);
+ lua_assert(!(pt->is_vararg & VARARG_NEEDSARG) ||
+ (pt->is_vararg & VARARG_HASARG));
+ check(pt->sizeupvalues <= pt->nups);
check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0);
- lua_assert(pt->numparams+pt->is_vararg <= pt->maxstacksize);
check(GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);
return 1;
}
-static int checkopenop (const Proto *pt, int pc) {
- Instruction i = pt->code[pc+1];
+#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1])
+
+int luaG_checkopenop (Instruction i) {
switch (GET_OPCODE(i)) {
case OP_CALL:
case OP_TAILCALL:
- case OP_RETURN: {
+ case OP_RETURN:
+ case OP_SETLIST: {
check(GETARG_B(i) == 0);
return 1;
}
- case OP_SETLISTO: return 1;
default: return 0; /* invalid instruction after an open call */
}
}
-static int checkRK (const Proto *pt, int r) {
- return (r < pt->maxstacksize || (r >= MAXSTACK && r-MAXSTACK < pt->sizek));
+static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) {
+ switch (mode) {
+ case OpArgN: check(r == 0); break;
+ case OpArgU: break;
+ case OpArgR: checkreg(pt, r); break;
+ case OpArgK:
+ check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize);
+ break;
+ }
+ return 1;
}
-static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
+static Instruction symbexec (const Proto *pt, int lastpc, int reg) {
int pc;
int last; /* stores position of last instruction that changed `reg' */
last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */
check(precheck(pt));
for (pc = 0; pc < lastpc; pc++) {
- const Instruction i = pt->code[pc];
+ Instruction i = pt->code[pc];
OpCode op = GET_OPCODE(i);
int a = GETARG_A(i);
int b = 0;
int c = 0;
+ check(op < NUM_OPCODES);
checkreg(pt, a);
switch (getOpMode(op)) {
case iABC: {
b = GETARG_B(i);
c = GETARG_C(i);
- if (testOpMode(op, OpModeBreg)) {
- checkreg(pt, b);
- }
- else if (testOpMode(op, OpModeBrk))
- check(checkRK(pt, b));
- if (testOpMode(op, OpModeCrk))
- check(checkRK(pt, c));
+ check(checkArgMode(pt, b, getBMode(op)));
+ check(checkArgMode(pt, c, getCMode(op)));
break;
}
case iABx: {
b = GETARG_Bx(i);
- if (testOpMode(op, OpModeK)) check(b < pt->sizek);
+ if (getBMode(op) == OpArgK) check(b < pt->sizek);
break;
}
case iAsBx: {
b = GETARG_sBx(i);
+ if (getBMode(op) == OpArgR) {
+ int dest = pc+1+b;
+ check(0 <= dest && dest < pt->sizecode);
+ if (dest > 0) {
+ /* cannot jump to a setlist count */
+ Instruction d = pt->code[dest-1];
+ check(!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0));
+ }
+ }
break;
}
}
- if (testOpMode(op, OpModesetA)) {
+ if (testAMode(op)) {
if (a == reg) last = pc; /* change register `a' */
}
- if (testOpMode(op, OpModeT)) {
+ if (testTMode(op)) {
check(pc+2 < pt->sizecode); /* check skip */
check(GET_OPCODE(pt->code[pc+1]) == OP_JMP);
}
@@ -399,20 +417,21 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
break;
}
case OP_CONCAT: {
- /* `c' is a register, and at least two operands */
- check(c < MAXSTACK && b < c);
+ check(b < c); /* at least two operands */
+ break;
+ }
+ case OP_TFORLOOP: {
+ check(c >= 1); /* at least one result (control variable) */
+ checkreg(pt, a+2+c); /* space for results */
+ if (reg >= a+2) last = pc; /* affect all regs above its base */
break;
}
- case OP_TFORLOOP:
- checkreg(pt, a+c+5);
- if (reg >= a) last = pc; /* affect all registers above base */
- /* go through */
case OP_FORLOOP:
- checkreg(pt, a+2);
+ case OP_FORPREP:
+ checkreg(pt, a+3);
/* go through */
case OP_JMP: {
int dest = pc+1+b;
- check(0 <= dest && dest < pt->sizecode);
/* not full check and jump is forward and do not skip `lastpc'? */
if (reg != NO_REG && pc < dest && dest <= lastpc)
pc += b; /* do the jump */
@@ -438,18 +457,29 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
break;
}
case OP_SETLIST: {
- checkreg(pt, a + (b&(LFIELDS_PER_FLUSH-1)) + 1);
+ if (b > 0) checkreg(pt, a + b);
+ if (c == 0) pc++;
break;
}
case OP_CLOSURE: {
- int nup;
+ int nup, j;
check(b < pt->sizep);
nup = pt->p[b]->nups;
check(pc + nup < pt->sizecode);
- for (; nup>0; nup--) {
- OpCode op1 = GET_OPCODE(pt->code[pc+nup]);
+ for (j = 1; j <= nup; j++) {
+ OpCode op1 = GET_OPCODE(pt->code[pc + j]);
check(op1 == OP_GETUPVAL || op1 == OP_MOVE);
}
+ if (reg != NO_REG) /* tracing? */
+ pc += nup; /* do not 'execute' these pseudo-instructions */
+ break;
+ }
+ case OP_VARARG: {
+ check((pt->is_vararg & VARARG_ISVARARG) &&
+ !(pt->is_vararg & VARARG_NEEDSARG));
+ b--;
+ if (b == LUA_MULTRET) check(checkopenop(pt, pc));
+ checkreg(pt, a+b-1);
break;
}
default: break;
@@ -466,28 +496,28 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
int luaG_checkcode (const Proto *pt) {
- return luaG_symbexec(pt, pt->sizecode, NO_REG);
+ return (symbexec(pt, pt->sizecode, NO_REG) != 0);
}
static const char *kname (Proto *p, int c) {
- c = c - MAXSTACK;
- if (c >= 0 && ttisstring(&p->k[c]))
- return svalue(&p->k[c]);
+ if (ISK(c) && ttisstring(&p->k[INDEXK(c)]))
+ return svalue(&p->k[INDEXK(c)]);
else
return "?";
}
-static const char *getobjname (CallInfo *ci, int stackpos, const char **name) {
+static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos,
+ const char **name) {
if (isLua(ci)) { /* a Lua function? */
Proto *p = ci_func(ci)->l.p;
- int pc = currentpc(ci);
+ int pc = currentpc(L, ci);
Instruction i;
*name = luaF_getlocalname(p, stackpos+1, pc);
if (*name) /* is a local? */
return "local";
- i = luaG_symbexec(p, pc, stackpos); /* try symbolic execution */
+ i = symbexec(p, pc, stackpos); /* try symbolic execution */
lua_assert(pc != -1);
switch (GET_OPCODE(i)) {
case OP_GETGLOBAL: {
@@ -500,7 +530,7 @@ static const char *getobjname (CallInfo *ci, int stackpos, const char **name) {
int a = GETARG_A(i);
int b = GETARG_B(i); /* move from `b' to `a' */
if (b < a)
- return getobjname(ci, b, name); /* get name for `b' */
+ return getobjname(L, ci, b, name); /* get name for `b' */
break;
}
case OP_GETTABLE: {
@@ -508,6 +538,11 @@ static const char *getobjname (CallInfo *ci, int stackpos, const char **name) {
*name = kname(p, k);
return "field";
}
+ case OP_GETUPVAL: {
+ int u = GETARG_B(i); /* upvalue index */
+ *name = p->upvalues ? getstr(p->upvalues[u]) : "?";
+ return "upvalue";
+ }
case OP_SELF: {
int k = GETARG_C(i); /* key index */
*name = kname(p, k);
@@ -520,21 +555,22 @@ static const char *getobjname (CallInfo *ci, int stackpos, const char **name) {
}
-static const char *getfuncname (CallInfo *ci, const char **name) {
+static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
Instruction i;
- if ((isLua(ci) && ci->u.l.tailcalls > 0) || !isLua(ci - 1))
+ if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1))
return NULL; /* calling function is not Lua (or is unknown) */
ci--; /* calling function */
- i = ci_func(ci)->l.p->code[currentpc(ci)];
- if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL)
- return getobjname(ci, GETARG_A(i), name);
+ i = ci_func(ci)->l.p->code[currentpc(L, ci)];
+ if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL ||
+ GET_OPCODE(i) == OP_TFORLOOP)
+ return getobjname(L, ci, GETARG_A(i), name);
else
return NULL; /* no useful name can be found */
}
/* only ANSI way to check whether a pointer points to an array */
-static int isinstack (CallInfo *ci, const TObject *o) {
+static int isinstack (CallInfo *ci, const TValue *o) {
StkId p;
for (p = ci->base; p < ci->top; p++)
if (o == p) return 1;
@@ -542,13 +578,14 @@ static int isinstack (CallInfo *ci, const TObject *o) {
}
-void luaG_typeerror (lua_State *L, const TObject *o, const char *op) {
+void luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
const char *name = NULL;
const char *t = luaT_typenames[ttype(o)];
const char *kind = (isinstack(L->ci, o)) ?
- getobjname(L->ci, o - L->base, &name) : NULL;
+ getobjname(L, L->ci, cast_int(o - L->base), &name) :
+ NULL;
if (kind)
- luaG_runerror(L, "attempt to %s %s `%s' (a %s value)",
+ luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)",
op, kind, name, t);
else
luaG_runerror(L, "attempt to %s a %s value", op, t);
@@ -562,15 +599,15 @@ void luaG_concaterror (lua_State *L, StkId p1, StkId p2) {
}
-void luaG_aritherror (lua_State *L, const TObject *p1, const TObject *p2) {
- TObject temp;
+void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) {
+ TValue temp;
if (luaV_tonumber(p1, &temp) == NULL)
p2 = p1; /* first operand is wrong */
luaG_typeerror(L, p2, "perform arithmetic on");
}
-int luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2) {
+int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
const char *t1 = luaT_typenames[ttype(p1)];
const char *t2 = luaT_typenames[ttype(p2)];
if (t1[2] == t2[2])
@@ -585,7 +622,7 @@ static void addinfo (lua_State *L, const char *msg) {
CallInfo *ci = L->ci;
if (isLua(ci)) { /* is Lua code? */
char buff[LUA_IDSIZE]; /* add file:line information */
- int line = currentline(ci);
+ int line = currentline(L, ci);
luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE);
luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
}
@@ -596,8 +633,8 @@ void luaG_errormsg (lua_State *L) {
if (L->errfunc != 0) { /* is there an error handling function? */
StkId errfunc = restorestack(L, L->errfunc);
if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR);
- setobjs2s(L->top, L->top - 1); /* move argument */
- setobjs2s(L->top - 1, errfunc); /* push function */
+ setobjs2s(L, L->top, L->top - 1); /* move argument */
+ setobjs2s(L, L->top - 1, errfunc); /* push function */
incr_top(L);
luaD_call(L, L->top - 2, 1); /* call it */
}
diff --git a/lib/lua/src/ldo.c b/lib/lua/src/ldo.c
index b23f8b1..6fc6d3c 100644
--- a/lib/lua/src/ldo.c
+++ b/lib/lua/src/ldo.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldo.c,v 1.8 2004-12-27 22:18:53 pixel Exp $
+** $Id: ldo.c,v 1.9 2007-07-27 10:05:53 pixel Exp $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@@ -10,6 +10,7 @@
#include <string.h>
#define ldo_c
+#define LUA_CORE
#include "lua.h"
@@ -34,7 +35,7 @@
/*
** {======================================================
-** Error-recovery functions (based on long jumps)
+** Error-recovery functions
** =======================================================
*/
@@ -42,24 +43,24 @@
/* chain list of long jump buffers */
struct lua_longjmp {
struct lua_longjmp *previous;
- jmp_buf b;
+ luai_jmpbuf b;
volatile int status; /* error code */
};
-static void seterrorobj (lua_State *L, int errcode, StkId oldtop) {
+void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {
switch (errcode) {
case LUA_ERRMEM: {
- setsvalue2s(oldtop, luaS_new(L, MEMERRMSG));
+ setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG));
break;
}
case LUA_ERRERR: {
- setsvalue2s(oldtop, luaS_new(L, "error in error handling"));
+ setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
break;
}
case LUA_ERRSYNTAX:
case LUA_ERRRUN: {
- setobjs2s(oldtop, L->top - 1); /* error message on current top */
+ setobjs2s(L, oldtop, L->top - 1); /* error message on current top */
break;
}
}
@@ -67,13 +68,41 @@ static void seterrorobj (lua_State *L, int errcode, StkId oldtop) {
}
+static void restore_stack_limit (lua_State *L) {
+ lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);
+ if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */
+ int inuse = cast_int(L->ci - L->base_ci);
+ if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */
+ luaD_reallocCI(L, LUAI_MAXCALLS);
+ }
+}
+
+
+static void resetstack (lua_State *L, int status) {
+ L->ci = L->base_ci;
+ L->base = L->ci->base;
+ luaF_close(L, L->base); /* close eventual pending closures */
+ luaD_seterrorobj(L, status, L->base);
+ L->nCcalls = 0;
+ L->allowhook = 1;
+ restore_stack_limit(L);
+ L->errfunc = 0;
+ L->errorJmp = NULL;
+}
+
+
void luaD_throw (lua_State *L, int errcode) {
if (L->errorJmp) {
L->errorJmp->status = errcode;
- longjmp(L->errorJmp->b, 1);
+ LUAI_THROW(L, L->errorJmp);
}
else {
- G(L)->panic(L);
+ L->status = cast_byte(errcode);
+ if (G(L)->panic) {
+ resetstack(L, errcode);
+ lua_unlock(L);
+ G(L)->panic(L);
+ }
exit(EXIT_FAILURE);
}
}
@@ -84,44 +113,38 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
lj.status = 0;
lj.previous = L->errorJmp; /* chain new error handler */
L->errorJmp = &lj;
- if (setjmp(lj.b) == 0)
+ LUAI_TRY(L, &lj,
(*f)(L, ud);
+ );
L->errorJmp = lj.previous; /* restore old error handler */
return lj.status;
}
-
-static void restore_stack_limit (lua_State *L) {
- L->stack_last = L->stack+L->stacksize-1;
- if (L->size_ci > LUA_MAXCALLS) { /* there was an overflow? */
- int inuse = (L->ci - L->base_ci);
- if (inuse + 1 < LUA_MAXCALLS) /* can `undo' overflow? */
- luaD_reallocCI(L, LUA_MAXCALLS);
- }
-}
-
/* }====================================================== */
-static void correctstack (lua_State *L, TObject *oldstack) {
+static void correctstack (lua_State *L, TValue *oldstack) {
CallInfo *ci;
GCObject *up;
L->top = (L->top - oldstack) + L->stack;
for (up = L->openupval; up != NULL; up = up->gch.next)
- gcotouv(up)->v = (gcotouv(up)->v - oldstack) + L->stack;
+ gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;
for (ci = L->base_ci; ci <= L->ci; ci++) {
ci->top = (ci->top - oldstack) + L->stack;
ci->base = (ci->base - oldstack) + L->stack;
+ ci->func = (ci->func - oldstack) + L->stack;
}
- L->base = L->ci->base;
+ L->base = (L->base - oldstack) + L->stack;
}
void luaD_reallocstack (lua_State *L, int newsize) {
- TObject *oldstack = L->stack;
- luaM_reallocvector(L, L->stack, L->stacksize, newsize, TObject);
- L->stacksize = newsize;
- L->stack_last = L->stack+newsize-1-EXTRA_STACK;
+ TValue *oldstack = L->stack;
+ int realsize = newsize + 1 + EXTRA_STACK;
+ lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);
+ luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue);
+ L->stacksize = realsize;
+ L->stack_last = L->stack+newsize;
correctstack(L, oldstack);
}
@@ -129,9 +152,9 @@ void luaD_reallocstack (lua_State *L, int newsize) {
void luaD_reallocCI (lua_State *L, int newsize) {
CallInfo *oldci = L->base_ci;
luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);
- L->size_ci = cast(unsigned short, newsize);
+ L->size_ci = newsize;
L->ci = (L->ci - oldci) + L->base_ci;
- L->end_ci = L->base_ci + L->size_ci;
+ L->end_ci = L->base_ci + L->size_ci - 1;
}
@@ -139,18 +162,19 @@ void luaD_growstack (lua_State *L, int n) {
if (n <= L->stacksize) /* double size is enough? */
luaD_reallocstack(L, 2*L->stacksize);
else
- luaD_reallocstack(L, L->stacksize + n + EXTRA_STACK);
+ luaD_reallocstack(L, L->stacksize + n);
}
-static void luaD_growCI (lua_State *L) {
- if (L->size_ci > LUA_MAXCALLS) /* overflow while handling overflow? */
+static CallInfo *growCI (lua_State *L) {
+ if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */
luaD_throw(L, LUA_ERRERR);
else {
luaD_reallocCI(L, 2*L->size_ci);
- if (L->size_ci > LUA_MAXCALLS)
+ if (L->size_ci > LUAI_MAXCALLS)
luaG_runerror(L, "stack overflow");
}
+ return ++L->ci;
}
@@ -165,9 +189,10 @@ void luaD_callhook (lua_State *L, int event, int line) {
if (event == LUA_HOOKTAILRET)
ar.i_ci = 0; /* tail call; no debug information about it */
else
- ar.i_ci = L->ci - L->base_ci;
+ ar.i_ci = cast_int(L->ci - L->base_ci);
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
L->ci->top = L->top + LUA_MINSTACK;
+ lua_assert(L->ci->top <= L->stack_last);
L->allowhook = 0; /* cannot call hooks inside a hook */
lua_unlock(L);
(*hook)(L, &ar);
@@ -180,90 +205,129 @@ void luaD_callhook (lua_State *L, int event, int line) {
}
-static void adjust_varargs (lua_State *L, int nfixargs, StkId base) {
+static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
int i;
- Table *htab;
- TObject nname;
- int actual = L->top - base; /* actual number of arguments */
- if (actual < nfixargs) {
- luaD_checkstack(L, nfixargs - actual);
- for (; actual < nfixargs; ++actual)
- setnilvalue(L->top++);
+ int nfixargs = p->numparams;
+ Table *htab = NULL;
+ StkId base, fixed;
+ for (; actual < nfixargs; ++actual)
+ setnilvalue(L->top++);
+#if defined(LUA_COMPAT_VARARG)
+ if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */
+ int nvar = actual - nfixargs; /* number of extra arguments */
+ lua_assert(p->is_vararg & VARARG_HASARG);
+ luaC_checkGC(L);
+ htab = luaH_new(L, nvar, 1); /* create `arg' table */
+ for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */
+ setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);
+ /* store counter in field `n' */
+ setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
}
- actual -= nfixargs; /* number of extra arguments */
- htab = luaH_new(L, actual, 1); /* create `arg' table */
- for (i=0; i<actual; i++) /* put extra arguments into `arg' table */
- setobj2n(luaH_setnum(L, htab, i+1), L->top - actual + i);
- /* store counter in field `n' */
- setsvalue(&nname, luaS_newliteral(L, "n"));
- setnvalue(luaH_set(L, htab, &nname), cast(lua_Number, actual));
- L->top -= actual; /* remove extra elements from the stack */
- sethvalue(L->top, htab);
- incr_top(L);
+#endif
+ /* move fixed parameters to final position */
+ fixed = L->top - actual; /* first fixed argument */
+ base = L->top; /* final position of first argument */
+ for (i=0; i<nfixargs; i++) {
+ setobjs2s(L, L->top++, fixed+i);
+ setnilvalue(fixed+i);
+ }
+ /* add `arg' parameter */
+ if (htab) {
+ sethvalue(L, L->top++, htab);
+ lua_assert(iswhite(obj2gco(htab)));
+ }
+ return base;
}
static StkId tryfuncTM (lua_State *L, StkId func) {
- const TObject *tm = luaT_gettmbyobj(L, func, TM_CALL);
+ const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL);
StkId p;
ptrdiff_t funcr = savestack(L, func);
if (!ttisfunction(tm))
luaG_typeerror(L, func, "call");
/* Open a hole inside the stack at `func' */
- for (p = L->top; p > func; p--) setobjs2s(p, p-1);
+ for (p = L->top; p > func; p--) setobjs2s(L, p, p-1);
incr_top(L);
func = restorestack(L, funcr); /* previous call may change stack */
- setobj2s(func, tm); /* tag method is the new function to be called */
+ setobj2s(L, func, tm); /* tag method is the new function to be called */
return func;
}
-StkId luaD_precall (lua_State *L, StkId func) {
+
+#define inc_ci(L) \
+ ((L->ci == L->end_ci) ? growCI(L) : \
+ (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci))
+
+
+int luaD_precall (lua_State *L, StkId func, int nresults) {
LClosure *cl;
- ptrdiff_t funcr = savestack(L, func);
+ ptrdiff_t funcr;
if (!ttisfunction(func)) /* `func' is not a function? */
func = tryfuncTM(L, func); /* check the `function' tag method */
- if (L->ci + 1 == L->end_ci) luaD_growCI(L);
- else condhardstacktests(luaD_reallocCI(L, L->size_ci));
+ funcr = savestack(L, func);
cl = &clvalue(func)->l;
+ L->ci->savedpc = L->savedpc;
if (!cl->isC) { /* Lua function? prepare its call */
CallInfo *ci;
+ StkId st, base;
Proto *p = cl->p;
- if (p->is_vararg) /* varargs? */
- adjust_varargs(L, p->numparams, func+1);
luaD_checkstack(L, p->maxstacksize);
- ci = ++L->ci; /* now `enter' new function */
- L->base = L->ci->base = restorestack(L, funcr) + 1;
+ func = restorestack(L, funcr);
+ if (!p->is_vararg) { /* no varargs? */
+ base = func + 1;
+ if (L->top > base + p->numparams)
+ L->top = base + p->numparams;
+ }
+ else { /* vararg function */
+ int nargs = cast_int(L->top - func) - 1;
+ base = adjust_varargs(L, p, nargs);
+ func = restorestack(L, funcr); /* previous call may change the stack */
+ }
+ ci = inc_ci(L); /* now `enter' new function */
+ ci->func = func;
+ L->base = ci->base = base;
ci->top = L->base + p->maxstacksize;
- ci->u.l.savedpc = p->code; /* starting point */
- ci->u.l.tailcalls = 0;
- ci->state = CI_SAVEDPC;
- while (L->top < ci->top)
- setnilvalue(L->top++);
+ lua_assert(ci->top <= L->stack_last);
+ L->savedpc = p->code; /* starting point */
+ ci->tailcalls = 0;
+ ci->nresults = nresults;
+ for (st = L->top; st < ci->top; st++)
+ setnilvalue(st);
L->top = ci->top;
- return NULL;
+ if (L->hookmask & LUA_MASKCALL) {
+ L->savedpc++; /* hooks assume 'pc' is already incremented */
+ luaD_callhook(L, LUA_HOOKCALL, -1);
+ L->savedpc--; /* correct 'pc' */
+ }
+ return PCRLUA;
}
else { /* if is a C function, call it */
CallInfo *ci;
int n;
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
- ci = ++L->ci; /* now `enter' new function */
- L->base = L->ci->base = restorestack(L, funcr) + 1;
+ ci = inc_ci(L); /* now `enter' new function */
+ ci->func = restorestack(L, funcr);
+ L->base = ci->base = ci->func + 1;
ci->top = L->top + LUA_MINSTACK;
- ci->state = CI_C; /* a C function */
+ lua_assert(ci->top <= L->stack_last);
+ ci->nresults = nresults;
if (L->hookmask & LUA_MASKCALL)
luaD_callhook(L, LUA_HOOKCALL, -1);
lua_unlock(L);
-#ifdef LUA_COMPATUPVALUES
- lua_pushupvalues(L);
-#endif
if (L->callwrap) {
- n = L->callwrap(L, clvalue(L->base - 1)->c.f); /* wrap the call */
+ n = L->callwrap(L, curr_func(L)->c.f); /* wrap the call */
} else {
- n = (*clvalue(L->base - 1)->c.f)(L); /* do the actual call */
+ n = (*curr_func(L)->c.f)(L); /* do the actual call */
}
lua_lock(L);
- return L->top - n;
+ if (n < 0) /* yielding? */
+ return PCRYIELD;
+ else {
+ luaD_poscall(L, L->top - n);
+ return PCRC;
+ }
}
}
@@ -271,29 +335,32 @@ StkId luaD_precall (lua_State *L, StkId func) {
static StkId callrethooks (lua_State *L, StkId firstResult) {
ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */
luaD_callhook(L, LUA_HOOKRET, -1);
- if (!(L->ci->state & CI_C)) { /* Lua function? */
- while (L->ci->u.l.tailcalls--) /* call hook for eventual tail calls */
+ if (f_isLua(L->ci)) { /* Lua function? */
+ while (L->ci->tailcalls--) /* call hook for eventual tail calls */
luaD_callhook(L, LUA_HOOKTAILRET, -1);
}
return restorestack(L, fr);
}
-void luaD_poscall (lua_State *L, int wanted, StkId firstResult) {
+int luaD_poscall (lua_State *L, StkId firstResult) {
StkId res;
+ int wanted, i;
+ CallInfo *ci;
if (L->hookmask & LUA_MASKRET)
firstResult = callrethooks(L, firstResult);
- res = L->base - 1; /* res == final position of 1st result */
- L->ci--;
- L->base = L->ci->base; /* restore base */
+ ci = L->ci--;
+ res = ci->func; /* res == final position of 1st result */
+ wanted = ci->nresults;
+ L->base = (ci - 1)->base; /* restore base */
+ L->savedpc = (ci - 1)->savedpc; /* restore savedpc */
/* move results to correct place */
- while (wanted != 0 && firstResult < L->top) {
- setobjs2s(res++, firstResult++);
- wanted--;
- }
- while (wanted-- > 0)
+ for (i = wanted; i != 0 && firstResult < L->top; i--)
+ setobjs2s(L, res++, firstResult++);
+ while (i-- > 0)
setnilvalue(res++);
L->top = res;
+ return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */
}
@@ -304,56 +371,47 @@ void luaD_poscall (lua_State *L, int wanted, StkId firstResult) {
** function position.
*/
void luaD_call (lua_State *L, StkId func, int nResults) {
- StkId firstResult;
- lua_assert(!(L->ci->state & CI_CALLING));
- if (++L->nCcalls >= LUA_MAXCCALLS) {
- if (L->nCcalls == LUA_MAXCCALLS)
+ if (++L->nCcalls >= LUAI_MAXCCALLS) {
+ if (L->nCcalls == LUAI_MAXCCALLS)
luaG_runerror(L, "C stack overflow");
- else if (L->nCcalls >= (LUA_MAXCCALLS + (LUA_MAXCCALLS>>3)))
+ else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
}
- firstResult = luaD_precall(L, func);
- if (firstResult == NULL) /* is a Lua function? */
- firstResult = luaV_execute(L); /* call it */
- luaD_poscall(L, nResults, firstResult);
+ if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */
+ luaV_execute(L, 1); /* call it */
L->nCcalls--;
luaC_checkGC(L);
}
static void resume (lua_State *L, void *ud) {
- StkId firstResult;
- int nargs = *cast(int *, ud);
+ StkId firstArg = cast(StkId, ud);
CallInfo *ci = L->ci;
- if (ci == L->base_ci) { /* no activation record? */
- lua_assert(nargs < L->top - L->base);
- luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */
+ if (L->status == 0) { /* start coroutine? */
+ lua_assert(ci == L->base_ci && firstArg > L->base);
+ if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA)
+ return;
}
- else { /* inside a yield */
- lua_assert(ci->state & CI_YIELD);
- if (ci->state & CI_C) { /* `common' yield? */
+ else { /* resuming from previous yield */
+ lua_assert(L->status == LUA_YIELD);
+ L->status = 0;
+ if (!f_isLua(ci)) { /* `common' yield? */
/* finish interrupted execution of `OP_CALL' */
- int nresults;
- lua_assert((ci-1)->state & CI_SAVEDPC);
- lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL ||
- GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL);
- nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1;
- luaD_poscall(L, nresults, L->top - nargs); /* complete it */
- if (nresults >= 0) L->top = L->ci->top;
- }
- else { /* yielded inside a hook: just continue its execution */
- ci->state &= ~CI_YIELD;
+ lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL ||
+ GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL);
+ if (luaD_poscall(L, firstArg)) /* complete it... */
+ L->top = L->ci->top; /* and correct top if not multiple results */
}
+ else /* yielded inside a hook: just continue its execution */
+ L->base = L->ci->base;
}
- firstResult = luaV_execute(L);
- if (firstResult != NULL) /* return? */
- luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */
+ luaV_execute(L, cast_int(L->ci - L->base_ci));
}
static int resume_error (lua_State *L, const char *msg) {
L->top = L->ci->base;
- setsvalue2s(L->top, luaS_new(L, msg));
+ setsvalue2s(L, L->top, luaS_new(L, msg));
incr_top(L);
lua_unlock(L);
return LUA_ERRRUN;
@@ -362,60 +420,47 @@ static int resume_error (lua_State *L, const char *msg) {
LUA_API int lua_resume (lua_State *L, int nargs) {
int status;
- lu_byte old_allowhooks;
lua_lock(L);
- if (L->ci == L->base_ci) {
- if (nargs >= L->top - L->base)
+ if (L->status != LUA_YIELD) {
+ if (L->status != 0)
return resume_error(L, "cannot resume dead coroutine");
+ else if (L->ci != L->base_ci)
+ return resume_error(L, "cannot resume non-suspended coroutine");
}
- else if (!(L->ci->state & CI_YIELD)) /* not inside a yield? */
- return resume_error(L, "cannot resume non-suspended coroutine");
- old_allowhooks = L->allowhook;
+ luai_userstateresume(L, nargs);
lua_assert(L->errfunc == 0 && L->nCcalls == 0);
- status = luaD_rawrunprotected(L, resume, &nargs);
+ status = luaD_rawrunprotected(L, resume, L->top - nargs);
if (status != 0) { /* error? */
- L->ci = L->base_ci; /* go back to initial level */
- L->base = L->ci->base;
- L->nCcalls = 0;
- luaF_close(L, L->base); /* close eventual pending closures */
- seterrorobj(L, status, L->base);
- L->allowhook = old_allowhooks;
- restore_stack_limit(L);
+ L->status = cast_byte(status); /* mark thread as `dead' */
+ luaD_seterrorobj(L, status, L->top);
+ L->ci->top = L->top;
}
+ else
+ status = L->status;
lua_unlock(L);
return status;
}
LUA_API int lua_yield (lua_State *L, int nresults) {
- CallInfo *ci;
+ luai_userstateyield(L, nresults);
lua_lock(L);
- ci = L->ci;
if (L->nCcalls > 0)
luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");
- if (ci->state & CI_C) { /* usual yield */
- if ((ci-1)->state & CI_C)
- luaG_runerror(L, "cannot yield a C function");
- if (L->top - nresults > L->base) { /* is there garbage in the stack? */
- int i;
- for (i=0; i<nresults; i++) /* move down results */
- setobjs2s(L->base + i, L->top - nresults + i);
- L->top = L->base + nresults;
- }
- } /* else it's an yield inside a hook: nothing to do */
- ci->state |= CI_YIELD;
+ L->base = L->top - nresults; /* protect stack slots below */
+ L->status = LUA_YIELD;
lua_unlock(L);
return -1;
}
+
LUA_API void lua_break (lua_State *L) {
- CallInfo * ci;
lua_lock(L);
- ci = L->ci;
- ci->state |= CI_BREAK;
+ L->do_break = 1;
lua_unlock(L);
}
+
int luaD_pcall (lua_State *L, Pfunc func, void *u,
ptrdiff_t old_top, ptrdiff_t ef) {
int status;
@@ -428,10 +473,11 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u,
if (status != 0) { /* an error occurred? */
StkId oldtop = restorestack(L, old_top);
luaF_close(L, oldtop); /* close eventual pending closures */
- seterrorobj(L, status, oldtop);
+ luaD_seterrorobj(L, status, oldtop);
L->nCcalls = oldnCcalls;
L->ci = restoreci(L, old_ci);
L->base = L->ci->base;
+ L->savedpc = L->ci->savedpc;
L->allowhook = old_allowhooks;
restore_stack_limit(L);
}
@@ -447,35 +493,34 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u,
struct SParser { /* data to `f_parser' */
ZIO *z;
Mbuffer buff; /* buffer to be used by the scanner */
- int bin;
+ const char *name;
};
static void f_parser (lua_State *L, void *ud) {
- struct SParser *p;
+ int i;
Proto *tf;
Closure *cl;
+ struct SParser *p = cast(struct SParser *, ud);
+ int c = luaZ_lookahead(p->z);
luaC_checkGC(L);
- p = cast(struct SParser *, ud);
- tf = p->bin ? luaU_undump(L, p->z, &p->buff) : luaY_parser(L, p->z, &p->buff);
- cl = luaF_newLclosure(L, 0, gt(L));
+ tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z,
+ &p->buff, p->name);
+ cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));
cl->l.p = tf;
- setclvalue(L->top, cl);
+ for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */
+ cl->l.upvals[i] = luaF_newupval(L);
+ setclvalue(L, L->top, cl);
incr_top(L);
}
-int luaD_protectedparser (lua_State *L, ZIO *z, int bin) {
+int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) {
struct SParser p;
int status;
- ptrdiff_t oldtopr = savestack(L, L->top); /* save current top */
- p.z = z; p.bin = bin;
+ p.z = z; p.name = name;
luaZ_initbuffer(L, &p.buff);
- status = luaD_rawrunprotected(L, f_parser, &p);
+ status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);
luaZ_freebuffer(L, &p.buff);
- if (status != 0) { /* error? */
- StkId oldtop = restorestack(L, oldtopr);
- seterrorobj(L, status, oldtop);
- }
return status;
}
diff --git a/lib/lua/src/ldump.c b/lib/lua/src/ldump.c
index 2bcfd5d..f7dd971 100644
--- a/lib/lua/src/ldump.c
+++ b/lib/lua/src/ldump.c
@@ -1,170 +1,164 @@
/*
-** $Id: ldump.c,v 1.4 2004-11-27 21:46:07 pixel Exp $
-** save bytecodes
+** $Id: ldump.c,v 1.5 2007-07-27 10:05:53 pixel Exp $
+** save precompiled Lua chunks
** See Copyright Notice in lua.h
*/
#include <stddef.h>
#define ldump_c
+#define LUA_CORE
#include "lua.h"
#include "lobject.h"
-#include "lopcodes.h"
#include "lstate.h"
#include "lundump.h"
-#define DumpVector(b,n,size,D) DumpBlock(b,(n)*(size),D)
-#define DumpLiteral(s,D) DumpBlock("" s,(sizeof(s))-1,D)
-
typedef struct {
lua_State* L;
- lua_Chunkwriter write;
+ lua_Writer writer;
void* data;
+ int strip;
+ int status;
} DumpState;
+#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D)
+#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D)
+
static void DumpBlock(const void* b, size_t size, DumpState* D)
{
- lua_unlock(D->L);
- (*D->write)(D->L,b,size,D->data);
- lua_lock(D->L);
+ if (D->status==0)
+ {
+ lua_unlock(D->L);
+ D->status=(*D->writer)(D->L,b,size,D->data);
+ lua_lock(D->L);
+ }
}
-static void DumpByte(int y, DumpState* D)
+static void DumpChar(int y, DumpState* D)
{
char x=(char)y;
- DumpBlock(&x,sizeof(x),D);
+ DumpVar(x,D);
}
static void DumpInt(int x, DumpState* D)
{
- DumpBlock(&x,sizeof(x),D);
+ DumpVar(x,D);
}
-static void DumpSize(size_t x, DumpState* D)
+static void DumpNumber(lua_Number x, DumpState* D)
{
- DumpBlock(&x,sizeof(x),D);
+ DumpVar(x,D);
}
-static void DumpNumber(lua_Number x, DumpState* D)
+static void DumpVector(const void* b, int n, size_t size, DumpState* D)
{
- DumpBlock(&x,sizeof(x),D);
+ DumpInt(n,D);
+ DumpMem(b,n,size,D);
}
-static void DumpString(TString* s, DumpState* D)
+static void DumpString(const TString* s, DumpState* D)
{
if (s==NULL || getstr(s)==NULL)
- DumpSize(0,D);
+ {
+ size_t size=0;
+ DumpVar(size,D);
+ }
else
{
size_t size=s->tsv.len+1; /* include trailing '\0' */
- DumpSize(size,D);
+ DumpVar(size,D);
DumpBlock(getstr(s),size,D);
}
}
-static void DumpCode(const Proto* f, DumpState* D)
-{
- DumpInt(f->sizecode,D);
- DumpVector(f->code,f->sizecode,sizeof(*f->code),D);
-}
-
-static void DumpLocals(const Proto* f, DumpState* D)
-{
- int i,n=f->sizelocvars;
- DumpInt(n,D);
- for (i=0; i<n; i++)
- {
- DumpString(f->locvars[i].varname,D);
- DumpInt(f->locvars[i].startpc,D);
- DumpInt(f->locvars[i].endpc,D);
- }
-}
-
-static void DumpLines(const Proto* f, DumpState* D)
-{
- DumpInt(f->sizelineinfo,D);
- DumpVector(f->lineinfo,f->sizelineinfo,sizeof(*f->lineinfo),D);
-}
-
-static void DumpUpvalues(const Proto* f, DumpState* D)
-{
- int i,n=f->sizeupvalues;
- DumpInt(n,D);
- for (i=0; i<n; i++) DumpString(f->upvalues[i],D);
-}
+#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D)
static void DumpFunction(const Proto* f, const TString* p, DumpState* D);
static void DumpConstants(const Proto* f, DumpState* D)
{
- int i,n;
- DumpInt(n=f->sizek,D);
+ int i,n=f->sizek;
+ DumpInt(n,D);
for (i=0; i<n; i++)
{
- const TObject* o=&f->k[i];
- DumpByte(ttype(o),D);
+ const TValue* o=&f->k[i];
+ DumpChar(ttype(o),D);
switch (ttype(o))
{
+ case LUA_TNIL:
+ break;
+ case LUA_TBOOLEAN:
+ DumpChar(bvalue(o),D);
+ break;
case LUA_TNUMBER:
DumpNumber(nvalue(o),D);
break;
case LUA_TSTRING:
- DumpString(tsvalue(o),D);
- break;
- case LUA_TNIL:
+ DumpString(rawtsvalue(o),D);
break;
default:
lua_assert(0); /* cannot happen */
break;
}
}
- DumpInt(n=f->sizep,D);
+ n=f->sizep;
+ DumpInt(n,D);
for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D);
}
+static void DumpDebug(const Proto* f, DumpState* D)
+{
+ int i,n;
+ n= (D->strip) ? 0 : f->sizelineinfo;
+ DumpVector(f->lineinfo,n,sizeof(int),D);
+ n= (D->strip) ? 0 : f->sizelocvars;
+ DumpInt(n,D);
+ for (i=0; i<n; i++)
+ {
+ DumpString(f->locvars[i].varname,D);
+ DumpInt(f->locvars[i].startpc,D);
+ DumpInt(f->locvars[i].endpc,D);
+ }
+ n= (D->strip) ? 0 : f->sizeupvalues;
+ DumpInt(n,D);
+ for (i=0; i<n; i++) DumpString(f->upvalues[i],D);
+}
+
static void DumpFunction(const Proto* f, const TString* p, DumpState* D)
{
- DumpString((f->source==p) ? NULL : f->source,D);
- DumpInt(f->lineDefined,D);
- DumpByte(f->nups,D);
- DumpByte(f->numparams,D);
- DumpByte(f->is_vararg,D);
- DumpByte(f->maxstacksize,D);
- DumpLines(f,D);
- DumpLocals(f,D);
- DumpUpvalues(f,D);
- DumpConstants(f,D);
+ DumpString((f->source==p || D->strip) ? NULL : f->source,D);
+ DumpInt(f->linedefined,D);
+ DumpInt(f->lastlinedefined,D);
+ DumpChar(f->nups,D);
+ DumpChar(f->numparams,D);
+ DumpChar(f->is_vararg,D);
+ DumpChar(f->maxstacksize,D);
DumpCode(f,D);
+ DumpConstants(f,D);
+ DumpDebug(f,D);
}
static void DumpHeader(DumpState* D)
{
- DumpLiteral(LUA_SIGNATURE,D);
- DumpByte(VERSION,D);
- DumpByte(luaU_endianness(),D);
- DumpByte(sizeof(int),D);
- DumpByte(sizeof(size_t),D);
- DumpByte(sizeof(Instruction),D);
- DumpByte(SIZE_OP,D);
- DumpByte(SIZE_A,D);
- DumpByte(SIZE_B,D);
- DumpByte(SIZE_C,D);
- DumpByte(sizeof(lua_Number),D);
- DumpNumber(TEST_NUMBER,D);
+ char h[LUAC_HEADERSIZE];
+ luaU_header(h);
+ DumpBlock(h,LUAC_HEADERSIZE,D);
}
/*
-** dump function as precompiled chunk
+** dump Lua function as precompiled chunk
*/
-void luaU_dump (lua_State* L, const Proto* Main, lua_Chunkwriter w, void* data)
+int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip)
{
DumpState D;
D.L=L;
- D.write=w;
+ D.writer=w;
D.data=data;
+ D.strip=strip;
+ D.status=0;
DumpHeader(&D);
- DumpFunction(Main,NULL,&D);
+ DumpFunction(f,NULL,&D);
+ return D.status;
}
-
diff --git a/lib/lua/src/lfunc.c b/lib/lua/src/lfunc.c
index 45a60cb..19fdc1a 100644
--- a/lib/lua/src/lfunc.c
+++ b/lib/lua/src/lfunc.c
@@ -1,13 +1,14 @@
/*
-** $Id: lfunc.c,v 1.5 2007-07-25 16:54:32 pixel Exp $
+** $Id: lfunc.c,v 1.6 2007-07-27 10:05:53 pixel Exp $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
-#include <stdlib.h>
+#include <stddef.h>
#define lfunc_c
+#define LUA_CORE
#include "lua.h"
@@ -18,57 +19,102 @@
#include "lstate.h"
-Closure *luaF_newCclosure (lua_State *L, int nelems) {
+
+Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) {
Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));
- luaC_link(L, valtogco(c), LUA_TFUNCTION);
+ luaC_link(L, obj2gco(c), LUA_TFUNCTION);
c->c.isC = 1;
- c->c.nupvalues = cast(lu_byte, nelems);
+ c->c.env = e;
+ c->c.nupvalues = cast_byte(nelems);
return c;
}
-Closure *luaF_newLclosure (lua_State *L, int nelems, TObject *e) {
+Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) {
Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));
- luaC_link(L, valtogco(c), LUA_TFUNCTION);
+ luaC_link(L, obj2gco(c), LUA_TFUNCTION);
c->l.isC = 0;
- c->l.g = *e;
- c->l.nupvalues = cast(lu_byte, nelems);
+ c->l.env = e;
+ c->l.nupvalues = cast_byte(nelems);
+ while (nelems--) c->l.upvals[nelems] = NULL;
return c;
}
+UpVal *luaF_newupval (lua_State *L) {
+ UpVal *uv = luaM_new(L, UpVal);
+ luaC_link(L, obj2gco(uv), LUA_TUPVAL);
+ uv->v = &uv->u.value;
+ setnilvalue(uv->v);
+ return uv;
+}
+
+
UpVal *luaF_findupval (lua_State *L, StkId level) {
+ global_State *g = G(L);
GCObject **pp = &L->openupval;
UpVal *p;
- UpVal *v;
- while ((p = ngcotouv(*pp)) != NULL && p->v >= level) {
- if (p->v == level) return p;
+ UpVal *uv;
+ while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) {
+ lua_assert(p->v != &p->u.value);
+ if (p->v == level) { /* found a corresponding upvalue? */
+ if (isdead(g, obj2gco(p))) /* is it dead? */
+ changewhite(obj2gco(p)); /* ressurect it */
+ return p;
+ }
pp = &p->next;
}
- v = luaM_new(L, UpVal); /* not found: create a new one */
- v->tt = LUA_TUPVAL;
- v->marked = 1; /* open upvalues should not be collected */
- v->v = level; /* current value lives in the stack */
- v->next = *pp; /* chain it in the proper position */
- *pp = valtogco(v);
- return v;
+ uv = luaM_new(L, UpVal); /* not found: create a new one */
+ uv->tt = LUA_TUPVAL;
+ uv->marked = luaC_white(g);
+ uv->v = level; /* current value lives in the stack */
+ uv->next = *pp; /* chain it in the proper position */
+ *pp = obj2gco(uv);
+ uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */
+ uv->u.l.next = g->uvhead.u.l.next;
+ uv->u.l.next->u.l.prev = uv;
+ g->uvhead.u.l.next = uv;
+ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
+ return uv;
+}
+
+
+static void unlinkupval (UpVal *uv) {
+ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
+ uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */
+ uv->u.l.prev->u.l.next = uv->u.l.next;
+}
+
+
+void luaF_freeupval (lua_State *L, UpVal *uv) {
+ if (uv->v != &uv->u.value) /* is it open? */
+ unlinkupval(uv); /* remove from open list */
+ luaM_free(L, uv); /* free upvalue */
}
void luaF_close (lua_State *L, StkId level) {
- UpVal *p;
- while ((p = ngcotouv(L->openupval)) != NULL && p->v >= level) {
- setobj(&p->value, p->v); /* save current value (write barrier) */
- p->v = &p->value; /* now current value lives here */
- L->openupval = p->next; /* remove from `open' list */
- luaC_link(L, valtogco(p), LUA_TUPVAL);
+ UpVal *uv;
+ global_State *g = G(L);
+ while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) {
+ GCObject *o = obj2gco(uv);
+ lua_assert(!isblack(o) && uv->v != &uv->u.value);
+ L->openupval = uv->next; /* remove from `open' list */
+ if (isdead(g, o))
+ luaF_freeupval(L, uv); /* free upvalue */
+ else {
+ unlinkupval(uv);
+ setobj(L, &uv->u.value, uv->v);
+ uv->v = &uv->u.value; /* now current value lives here */
+ luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */
+ }
}
}
Proto *luaF_newproto (lua_State *L) {
Proto *f = luaM_new(L, Proto);
- luaC_link(L, valtogco(f), LUA_TPROTO);
+ luaC_link(L, obj2gco(f), LUA_TPROTO);
f->k = NULL;
f->sizek = 0;
f->p = NULL;
@@ -85,7 +131,8 @@ Proto *luaF_newproto (lua_State *L) {
f->lineinfo = NULL;
f->sizelocvars = 0;
f->locvars = NULL;
- f->lineDefined = 0;
+ f->linedefined = 0;
+ f->lastlinedefined = 0;
f->source = NULL;
return f;
}
@@ -94,18 +141,18 @@ Proto *luaF_newproto (lua_State *L) {
void luaF_freeproto (lua_State *L, Proto *f) {
luaM_freearray(L, f->code, f->sizecode, Instruction);
luaM_freearray(L, f->p, f->sizep, Proto *);
- luaM_freearray(L, f->k, f->sizek, TObject);
+ luaM_freearray(L, f->k, f->sizek, TValue);
luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);
luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);
- luaM_freelem(L, f);
+ luaM_free(L, f);
}
void luaF_freeclosure (lua_State *L, Closure *c) {
int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) :
sizeLclosure(c->l.nupvalues);
- luaM_free(L, c, size);
+ luaM_freemem(L, c, size);
}
diff --git a/lib/lua/src/lgc.c b/lib/lua/src/lgc.c
index dbc022d..56c2aa4 100644
--- a/lib/lua/src/lgc.c
+++ b/lib/lua/src/lgc.c
@@ -1,5 +1,5 @@
/*
-** $Id: lgc.c,v 1.6 2007-07-25 16:54:32 pixel Exp $
+** $Id: lgc.c,v 1.7 2007-07-27 10:05:54 pixel Exp $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -7,6 +7,7 @@
#include <string.h>
#define lgc_c
+#define LUA_CORE
#include "lua.h"
@@ -22,325 +23,352 @@
#include "ltm.h"
-typedef struct GCState {
- GCObject *tmark; /* list of marked objects to be traversed */
- GCObject *wk; /* list of traversed key-weak tables (to be cleared) */
- GCObject *wv; /* list of traversed value-weak tables */
- GCObject *wkv; /* list of traversed key-value weak tables */
- global_State *g;
-} GCState;
+#define GCSTEPSIZE 1024u
+#define GCSWEEPMAX 40
+#define GCSWEEPCOST 10
+#define GCFINALIZECOST 100
-/*
-** some userful bit tricks
-*/
-#define setbit(x,b) ((x) |= (1<<(b)))
-#define resetbit(x,b) ((x) &= cast(lu_byte, ~(1<<(b))))
-#define testbit(x,b) ((x) & (1<<(b)))
+#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS))
+
+#define makewhite(g,x) \
+ ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g)))
+
+#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
+#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT)
-#define unmark(x) resetbit((x)->gch.marked, 0)
-#define ismarked(x) ((x)->gch.marked & ((1<<4)|1))
+#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT)
-#define stringmark(s) setbit((s)->tsv.marked, 0)
+#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT)
+#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT)
-#define isfinalized(u) (!testbit((u)->uv.marked, 1))
-#define markfinalized(u) resetbit((u)->uv.marked, 1)
+#define KEYWEAK bitmask(KEYWEAKBIT)
+#define VALUEWEAK bitmask(VALUEWEAKBIT)
-#define KEYWEAKBIT 1
-#define VALUEWEAKBIT 2
-#define KEYWEAK (1<<KEYWEAKBIT)
-#define VALUEWEAK (1<<VALUEWEAKBIT)
+#define markvalue(g,o) { checkconsistency(o); \
+ if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); }
-#define markobject(st,o) { checkconsistency(o); \
- if (iscollectable(o) && !ismarked(gcvalue(o))) reallymarkobject(st,gcvalue(o)); }
+#define markobject(g,t) { if (iswhite(obj2gco(t))) \
+ reallymarkobject(g, obj2gco(t)); }
-#define condmarkobject(st,o,c) { checkconsistency(o); \
- if (iscollectable(o) && !ismarked(gcvalue(o)) && (c)) \
- reallymarkobject(st,gcvalue(o)); }
-#define markvalue(st,t) { if (!ismarked(valtogco(t))) \
- reallymarkobject(st, valtogco(t)); }
+#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause)
+static void removeentry (Node *n) {
+ lua_assert(ttisnil(gval(n)));
+ if (iscollectable(gkey(n)))
+ setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */
+}
+
-static void reallymarkobject (GCState *st, GCObject *o) {
- lua_assert(!ismarked(o));
- setbit(o->gch.marked, 0); /* mark object */
+static void reallymarkobject (global_State *g, GCObject *o) {
+ lua_assert(iswhite(o) && !isdead(g, o));
+ white2gray(o);
switch (o->gch.tt) {
+ case LUA_TSTRING: {
+ return;
+ }
case LUA_TUSERDATA: {
- markvalue(st, gcotou(o)->uv.metatable);
- break;
+ Table *mt = gco2u(o)->metatable;
+ gray2black(o); /* udata are never gray */
+ if (mt) markobject(g, mt);
+ markobject(g, gco2u(o)->env);
+ return;
+ }
+ case LUA_TUPVAL: {
+ UpVal *uv = gco2uv(o);
+ markvalue(g, uv->v);
+ if (uv->v == &uv->u.value) /* closed? */
+ gray2black(o); /* open upvalues are never black */
+ return;
}
case LUA_TFUNCTION: {
- gcotocl(o)->c.gclist = st->tmark;
- st->tmark = o;
+ gco2cl(o)->c.gclist = g->gray;
+ g->gray = o;
break;
}
case LUA_TTABLE: {
- gcotoh(o)->gclist = st->tmark;
- st->tmark = o;
+ gco2h(o)->gclist = g->gray;
+ g->gray = o;
break;
}
case LUA_TTHREAD: {
- gcototh(o)->gclist = st->tmark;
- st->tmark = o;
+ gco2th(o)->gclist = g->gray;
+ g->gray = o;
break;
}
case LUA_TPROTO: {
- gcotop(o)->gclist = st->tmark;
- st->tmark = o;
+ gco2p(o)->gclist = g->gray;
+ g->gray = o;
break;
}
- default: lua_assert(o->gch.tt == LUA_TSTRING);
+ default: lua_assert(0);
}
}
-static void marktmu (GCState *st) {
- GCObject *u;
- for (u = st->g->tmudata; u; u = u->gch.next) {
- unmark(u); /* may be marked, if left from previous GC */
- reallymarkobject(st, u);
+static void marktmu (global_State *g) {
+ GCObject *u = g->tmudata;
+ if (u) {
+ do {
+ u = u->gch.next;
+ makewhite(g, u); /* may be marked, if left from previous GC */
+ reallymarkobject(g, u);
+ } while (u != g->tmudata);
}
}
/* move `dead' udata that need finalization to list `tmudata' */
-size_t luaC_separateudata (lua_State *L) {
+size_t luaC_separateudata (lua_State *L, int all) {
+ global_State *g = G(L);
size_t deadmem = 0;
- GCObject **p = &G(L)->rootudata;
+ GCObject **p = &g->mainthread->next;
GCObject *curr;
- GCObject *collected = NULL; /* to collect udata with gc event */
- GCObject **lastcollected = &collected;
while ((curr = *p) != NULL) {
- lua_assert(curr->gch.tt == LUA_TUSERDATA);
- if (ismarked(curr) || isfinalized(gcotou(curr)))
+ if (!(iswhite(curr) || all) || isfinalized(gco2u(curr)))
p = &curr->gch.next; /* don't bother with them */
-
- else if (fasttm(L, gcotou(curr)->uv.metatable, TM_GC) == NULL) {
- markfinalized(gcotou(curr)); /* don't need finalization */
+ else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) {
+ markfinalized(gco2u(curr)); /* don't need finalization */
p = &curr->gch.next;
}
else { /* must call its gc method */
- deadmem += sizeudata(gcotou(curr)->uv.len);
+ deadmem += sizeudata(gco2u(curr));
+ markfinalized(gco2u(curr));
*p = curr->gch.next;
- curr->gch.next = NULL; /* link `curr' at the end of `collected' list */
- *lastcollected = curr;
- lastcollected = &curr->gch.next;
+ /* link `curr' at the end of `tmudata' list */
+ if (g->tmudata == NULL) /* list is empty? */
+ g->tmudata = curr->gch.next = curr; /* creates a circular list */
+ else {
+ curr->gch.next = g->tmudata->gch.next;
+ g->tmudata->gch.next = curr;
+ g->tmudata = curr;
+ }
}
}
- /* insert collected udata with gc event into `tmudata' list */
- *lastcollected = G(L)->tmudata;
- G(L)->tmudata = collected;
return deadmem;
}
-static void removekey (Node *n) {
- setnilvalue(gval(n)); /* remove corresponding value ... */
- if (iscollectable(gkey(n)))
- setttype(gkey(n), LUA_TNONE); /* dead key; remove it */
-}
-
-
-static void traversetable (GCState *st, Table *h) {
+static int traversetable (global_State *g, Table *h) {
int i;
int weakkey = 0;
int weakvalue = 0;
- const TObject *mode;
- markvalue(st, h->metatable);
- lua_assert(h->lsizenode || h->node == st->g->dummynode);
- mode = gfasttm(st->g, h->metatable, TM_MODE);
+ const TValue *mode;
+ if (h->metatable)
+ markobject(g, h->metatable);
+ mode = gfasttm(g, h->metatable, TM_MODE);
if (mode && ttisstring(mode)) { /* is there a weak mode? */
weakkey = (strchr(svalue(mode), 'k') != NULL);
weakvalue = (strchr(svalue(mode), 'v') != NULL);
if (weakkey || weakvalue) { /* is really weak? */
- GCObject **weaklist;
h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */
- h->marked |= cast(lu_byte, (weakkey << KEYWEAKBIT) |
- (weakvalue << VALUEWEAKBIT));
- weaklist = (weakkey && weakvalue) ? &st->wkv :
- (weakkey) ? &st->wk :
- &st->wv;
- h->gclist = *weaklist; /* must be cleared after GC, ... */
- *weaklist = valtogco(h); /* ... so put in the appropriate list */
+ h->marked |= cast_byte((weakkey << KEYWEAKBIT) |
+ (weakvalue << VALUEWEAKBIT));
+ h->gclist = g->weak; /* must be cleared after GC, ... */
+ g->weak = obj2gco(h); /* ... so put in the appropriate list */
}
}
+ if (weakkey && weakvalue) return 1;
if (!weakvalue) {
i = h->sizearray;
while (i--)
- markobject(st, &h->array[i]);
+ markvalue(g, &h->array[i]);
}
i = sizenode(h);
while (i--) {
Node *n = gnode(h, i);
- if (!ttisnil(gval(n))) {
+ lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n)));
+ if (ttisnil(gval(n)))
+ removeentry(n); /* remove empty entries */
+ else {
lua_assert(!ttisnil(gkey(n)));
- condmarkobject(st, gkey(n), !weakkey);
- condmarkobject(st, gval(n), !weakvalue);
+ if (!weakkey) markvalue(g, gkey(n));
+ if (!weakvalue) markvalue(g, gval(n));
}
}
+ return weakkey || weakvalue;
}
-static void traverseproto (GCState *st, Proto *f) {
+/*
+** All marks are conditional because a GC may happen while the
+** prototype is still being created
+*/
+static void traverseproto (global_State *g, Proto *f) {
int i;
- stringmark(f->source);
- for (i=0; i<f->sizek; i++) { /* mark literal strings */
- if (ttisstring(f->k+i))
- stringmark(tsvalue(f->k+i));
+ if (f->source) stringmark(f->source);
+ for (i=0; i<f->sizek; i++) /* mark literals */
+ markvalue(g, &f->k[i]);
+ for (i=0; i<f->sizeupvalues; i++) { /* mark upvalue names */
+ if (f->upvalues[i])
+ stringmark(f->upvalues[i]);
+ }
+ for (i=0; i<f->sizep; i++) { /* mark nested protos */
+ if (f->p[i])
+ markobject(g, f->p[i]);
+ }
+ for (i=0; i<f->sizelocvars; i++) { /* mark local-variable names */
+ if (f->locvars[i].varname)
+ stringmark(f->locvars[i].varname);
}
- for (i=0; i<f->sizeupvalues; i++) /* mark upvalue names */
- stringmark(f->upvalues[i]);
- for (i=0; i<f->sizep; i++) /* mark nested protos */
- markvalue(st, f->p[i]);
- for (i=0; i<f->sizelocvars; i++) /* mark local-variable names */
- stringmark(f->locvars[i].varname);
- lua_assert(luaG_checkcode(f));
}
-static void traverseclosure (GCState *st, Closure *cl) {
+static void traverseclosure (global_State *g, Closure *cl) {
+ markobject(g, cl->c.env);
if (cl->c.isC) {
int i;
for (i=0; i<cl->c.nupvalues; i++) /* mark its upvalues */
- markobject(st, &cl->c.upvalue[i]);
+ markvalue(g, &cl->c.upvalue[i]);
}
else {
int i;
lua_assert(cl->l.nupvalues == cl->l.p->nups);
- markvalue(st, hvalue(&cl->l.g));
- markvalue(st, cl->l.p);
- for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */
- UpVal *u = cl->l.upvals[i];
- markobject(st, u->v);
- u->marked = 1;
- }
+ markobject(g, cl->l.p);
+ for (i=0; i<cl->l.nupvalues; i++) /* mark its upvalues */
+ markobject(g, cl->l.upvals[i]);
}
}
static void checkstacksizes (lua_State *L, StkId max) {
- int used = L->ci - L->base_ci; /* number of `ci' in use */
- if (4*used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci)
+ int ci_used = cast_int(L->ci - L->base_ci); /* number of `ci' in use */
+ int s_used = cast_int(max - L->stack); /* part of stack in use */
+ if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */
+ return; /* do not touch the stacks */
+ if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci)
luaD_reallocCI(L, L->size_ci/2); /* still big enough... */
- else condhardstacktests(luaD_reallocCI(L, L->size_ci));
- used = max - L->stack; /* part of stack in use */
- if (4*used < L->stacksize && 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize)
+ condhardstacktests(luaD_reallocCI(L, ci_used + 1));
+ if (4*s_used < L->stacksize &&
+ 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize)
luaD_reallocstack(L, L->stacksize/2); /* still big enough... */
- else condhardstacktests(luaD_reallocstack(L, L->stacksize));
+ condhardstacktests(luaD_reallocstack(L, s_used));
}
-static void traversestack (GCState *st, lua_State *L1) {
+static void traversestack (global_State *g, lua_State *l) {
StkId o, lim;
CallInfo *ci;
- markobject(st, gt(L1));
- lim = L1->top;
- for (ci = L1->base_ci; ci <= L1->ci; ci++) {
- lua_assert(ci->top <= L1->stack_last);
- lua_assert(ci->state & (CI_C | CI_HASFRAME | CI_SAVEDPC));
- if (lim < ci->top)
- lim = ci->top;
+ markvalue(g, gt(l));
+ lim = l->top;
+ for (ci = l->base_ci; ci <= l->ci; ci++) {
+ lua_assert(ci->top <= l->stack_last);
+ if (lim < ci->top) lim = ci->top;
}
- for (o = L1->stack; o < L1->top; o++)
- markobject(st, o);
+ for (o = l->stack; o < l->top; o++)
+ markvalue(g, o);
for (; o <= lim; o++)
setnilvalue(o);
- checkstacksizes(L1, lim);
+ checkstacksizes(l, lim);
}
-static lu_mem propagatemarks (GCState *st) {
- lu_mem mf = 0;
- while (st->tmark) { /* traverse marked objects */
- switch (st->tmark->gch.tt) {
- case LUA_TTABLE: {
- Table *h = gcotoh(st->tmark);
- st->tmark = h->gclist;
- traversetable(st, h);
- mf += sizeof(Table) + sizeof(TObject) * h->sizearray +
- sizeof(Node) * sizenode(h);
- break;
- }
- case LUA_TFUNCTION: {
- Closure *cl = gcotocl(st->tmark);
- st->tmark = cl->c.gclist;
- traverseclosure(st, cl);
- mf += (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :
- sizeLclosure(cl->l.nupvalues);
- break;
- }
- case LUA_TTHREAD: {
- lua_State *th = gcototh(st->tmark);
- st->tmark = th->gclist;
- traversestack(st, th);
- mf += sizeof(lua_State) + sizeof(TObject) * th->stacksize +
- sizeof(CallInfo) * th->size_ci;
- break;
- }
- case LUA_TPROTO: {
- Proto *p = gcotop(st->tmark);
- st->tmark = p->gclist;
- traverseproto(st, p);
- /* do not need 'mf' for this case (cannot happen inside a udata) */
- break;
- }
- default: lua_assert(0);
+/*
+** traverse one gray object, turning it to black.
+** Returns `quantity' traversed.
+*/
+static l_mem propagatemark (global_State *g) {
+ GCObject *o = g->gray;
+ lua_assert(isgray(o));
+ gray2black(o);
+ switch (o->gch.tt) {
+ case LUA_TTABLE: {
+ Table *h = gco2h(o);
+ g->gray = h->gclist;
+ if (traversetable(g, h)) /* table is weak? */
+ black2gray(o); /* keep it gray */
+ return sizeof(Table) + sizeof(TValue) * h->sizearray +
+ sizeof(Node) * sizenode(h);
+ }
+ case LUA_TFUNCTION: {
+ Closure *cl = gco2cl(o);
+ g->gray = cl->c.gclist;
+ traverseclosure(g, cl);
+ return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :
+ sizeLclosure(cl->l.nupvalues);
}
+ case LUA_TTHREAD: {
+ lua_State *th = gco2th(o);
+ g->gray = th->gclist;
+ th->gclist = g->grayagain;
+ g->grayagain = o;
+ black2gray(o);
+ traversestack(g, th);
+ return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
+ sizeof(CallInfo) * th->size_ci;
+ }
+ case LUA_TPROTO: {
+ Proto *p = gco2p(o);
+ g->gray = p->gclist;
+ traverseproto(g, p);
+ return sizeof(Proto) + sizeof(Instruction) * p->sizecode +
+ sizeof(Proto *) * p->sizep +
+ sizeof(TValue) * p->sizek +
+ sizeof(int) * p->sizelineinfo +
+ sizeof(LocVar) * p->sizelocvars +
+ sizeof(TString *) * p->sizeupvalues;
+ }
+ default: lua_assert(0); return 0;
}
- return mf;
}
-static int valismarked (const TObject *o) {
- if (ttisstring(o))
- stringmark(tsvalue(o)); /* strings are `values', so are never weak */
- return !iscollectable(o) || testbit(o->value.gc->gch.marked, 0);
+static size_t propagateall (global_State *g) {
+ size_t m = 0;
+ while (g->gray) m += propagatemark(g);
+ return m;
}
/*
-** clear collected keys from weaktables
+** The next function tells whether a key or value can be cleared from
+** a weak table. Non-collectable objects are never removed from weak
+** tables. Strings behave as `values', so are never removed too. for
+** other objects: if really collected, cannot keep them; for userdata
+** being finalized, keep them in keys, but not in values
*/
-static void cleartablekeys (GCObject *l) {
- while (l) {
- Table *h = gcotoh(l);
- int i = sizenode(h);
- lua_assert(h->marked & KEYWEAK);
- while (i--) {
- Node *n = gnode(h, i);
- if (!valismarked(gkey(n))) /* key was collected? */
- removekey(n); /* remove entry from table */
- }
- l = h->gclist;
+static int iscleared (const TValue *o, int iskey) {
+ if (!iscollectable(o)) return 0;
+ if (ttisstring(o)) {
+ stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */
+ return 0;
}
+ return iswhite(gcvalue(o)) ||
+ (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o))));
}
/*
-** clear collected values from weaktables
+** clear collected entries from weaktables
*/
-static void cleartablevalues (GCObject *l) {
+static void cleartable (GCObject *l) {
while (l) {
- Table *h = gcotoh(l);
+ Table *h = gco2h(l);
int i = h->sizearray;
- lua_assert(h->marked & VALUEWEAK);
- while (i--) {
- TObject *o = &h->array[i];
- if (!valismarked(o)) /* value was collected? */
- setnilvalue(o); /* remove value */
+ lua_assert(testbit(h->marked, VALUEWEAKBIT) ||
+ testbit(h->marked, KEYWEAKBIT));
+ if (testbit(h->marked, VALUEWEAKBIT)) {
+ while (i--) {
+ TValue *o = &h->array[i];
+ if (iscleared(o, 0)) /* value was collected? */
+ setnilvalue(o); /* remove value */
+ }
}
i = sizenode(h);
while (i--) {
Node *n = gnode(h, i);
- if (!valismarked(gval(n))) /* value was collected? */
- removekey(n); /* remove entry from table */
+ if (!ttisnil(gval(n)) && /* non-empty entry? */
+ (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) {
+ setnilvalue(gval(n)); /* remove value ... */
+ removeentry(n); /* remove entry from table */
+ }
}
l = h->gclist;
}
@@ -349,21 +377,22 @@ static void cleartablevalues (GCObject *l) {
static void freeobj (lua_State *L, GCObject *o) {
switch (o->gch.tt) {
- case LUA_TPROTO: luaF_freeproto(L, gcotop(o)); break;
- case LUA_TFUNCTION: luaF_freeclosure(L, gcotocl(o)); break;
- case LUA_TUPVAL: luaM_freelem(L, gcotouv(o)); break;
- case LUA_TTABLE: luaH_free(L, gcotoh(o)); break;
+ case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break;
+ case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break;
+ case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break;
+ case LUA_TTABLE: luaH_free(L, gco2h(o)); break;
case LUA_TTHREAD: {
- lua_assert(gcototh(o) != L && gcototh(o) != G(L)->mainthread);
- luaE_freethread(L, gcototh(o));
+ lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread);
+ luaE_freethread(L, gco2th(o));
break;
}
case LUA_TSTRING: {
- luaM_free(L, o, sizestring(gcotots(o)->tsv.len));
+ G(L)->strt.nuse--;
+ luaM_freemem(L, o, sizestring(gco2ts(o)));
break;
}
case LUA_TUSERDATA: {
- luaM_free(L, o, sizeudata(gcotou(o)->uv.len));
+ luaM_freemem(L, o, sizeudata(gco2u(o)));
break;
}
default: lua_assert(0);
@@ -371,135 +400,312 @@ static void freeobj (lua_State *L, GCObject *o) {
}
-static int sweeplist (lua_State *L, GCObject **p, int limit) {
+
+#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM)
+
+
+static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
GCObject *curr;
- int count = 0; /* number of collected items */
- while ((curr = *p) != NULL) {
- if ((curr->gch.marked & ~(KEYWEAK | VALUEWEAK)) > limit) {
- unmark(curr);
+ global_State *g = G(L);
+ int deadmask = otherwhite(g);
+ while ((curr = *p) != NULL && count-- > 0) {
+ if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */
+ sweepwholelist(L, &gco2th(curr)->openupval);
+ if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */
+ lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT));
+ makewhite(g, curr); /* make it white (for next cycle) */
p = &curr->gch.next;
}
- else {
- count++;
+ else { /* must erase `curr' */
+ lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT));
*p = curr->gch.next;
+ if (curr == g->rootgc) /* is the first element of the list? */
+ g->rootgc = curr->gch.next; /* adjust first */
freeobj(L, curr);
}
}
- return count;
-}
-
-
-static void sweepstrings (lua_State *L, int all) {
- int i;
- for (i=0; i<G(L)->strt.size; i++) { /* for each list */
- G(L)->strt.nuse -= sweeplist(L, &G(L)->strt.hash[i], all);
- }
+ return p;
}
-static void checkSizes (lua_State *L, size_t deadmem) {
+static void checkSizes (lua_State *L) {
+ global_State *g = G(L);
/* check size of string hash */
- if (G(L)->strt.nuse < cast(ls_nstr, G(L)->strt.size/4) &&
- G(L)->strt.size > MINSTRTABSIZE*2)
- luaS_resize(L, G(L)->strt.size/2); /* table is too big */
+ if (g->strt.nuse < cast(lu_int32, g->strt.size/4) &&
+ g->strt.size > MINSTRTABSIZE*2)
+ luaS_resize(L, g->strt.size/2); /* table is too big */
/* check size of buffer */
- if (luaZ_sizebuffer(&G(L)->buff) > LUA_MINBUFFER*2) { /* buffer too big? */
- size_t newsize = luaZ_sizebuffer(&G(L)->buff) / 2;
- luaZ_resizebuffer(L, &G(L)->buff, newsize);
+ if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */
+ size_t newsize = luaZ_sizebuffer(&g->buff) / 2;
+ luaZ_resizebuffer(L, &g->buff, newsize);
}
- G(L)->GCthreshold = 2*G(L)->nblocks - deadmem; /* new threshold */
}
-static void do1gcTM (lua_State *L, Udata *udata) {
- const TObject *tm = fasttm(L, udata->uv.metatable, TM_GC);
+static void GCTM (lua_State *L) {
+ global_State *g = G(L);
+ GCObject *o = g->tmudata->gch.next; /* get first element */
+ Udata *udata = rawgco2u(o);
+ const TValue *tm;
+ /* remove udata from `tmudata' */
+ if (o == g->tmudata) /* last element? */
+ g->tmudata = NULL;
+ else
+ g->tmudata->gch.next = udata->uv.next;
+ udata->uv.next = g->mainthread->next; /* return it to `root' list */
+ g->mainthread->next = o;
+ makewhite(g, o);
+ tm = fasttm(L, udata->uv.metatable, TM_GC);
if (tm != NULL) {
- setobj2s(L->top, tm);
- setuvalue(L->top+1, udata);
+ lu_byte oldah = L->allowhook;
+ lu_mem oldt = g->GCthreshold;
+ L->allowhook = 0; /* stop debug hooks during GC tag method */
+ g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */
+ setobj2s(L, L->top, tm);
+ setuvalue(L, L->top+1, udata);
L->top += 2;
luaD_call(L, L->top - 2, 0);
+ L->allowhook = oldah; /* restore hooks */
+ g->GCthreshold = oldt; /* restore threshold */
}
}
+/*
+** Call all GC tag methods
+*/
void luaC_callGCTM (lua_State *L) {
- lu_byte oldah = L->allowhook;
- L->allowhook = 0; /* stop debug hooks during GC tag methods */
- L->top++; /* reserve space to keep udata while runs its gc method */
- while (G(L)->tmudata != NULL) {
- GCObject *o = G(L)->tmudata;
- Udata *udata = gcotou(o);
- G(L)->tmudata = udata->uv.next; /* remove udata from `tmudata' */
- udata->uv.next = G(L)->rootudata; /* return it to `root' list */
- G(L)->rootudata = o;
- setuvalue(L->top - 1, udata); /* keep a reference to it */
- unmark(o);
- markfinalized(udata);
- do1gcTM(L, udata);
- }
- L->top--;
- L->allowhook = oldah; /* restore hooks */
+ while (G(L)->tmudata)
+ GCTM(L);
+}
+
+
+void luaC_freeall (lua_State *L) {
+ global_State *g = G(L);
+ int i;
+ g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */
+ sweepwholelist(L, &g->rootgc);
+ for (i = 0; i < g->strt.size; i++) /* free all string lists */
+ sweepwholelist(L, &g->strt.hash[i]);
}
-void luaC_sweep (lua_State *L, int all) {
- if (all) all = 256; /* larger than any mark */
- sweeplist(L, &G(L)->rootudata, all);
- sweepstrings(L, all);
- sweeplist(L, &G(L)->rootgc, all);
+static void markmt (global_State *g) {
+ int i;
+ for (i=0; i<NUM_TAGS; i++)
+ if (g->mt[i]) markobject(g, g->mt[i]);
}
/* mark root set */
-static void markroot (GCState *st, lua_State *L) {
- global_State *g = st->g;
- markobject(st, defaultmeta(L));
- markobject(st, registry(L));
- traversestack(st, g->mainthread);
- if (L != g->mainthread) /* another thread is running? */
- markvalue(st, L); /* cannot collect it */
+static void markroot (lua_State *L) {
+ global_State *g = G(L);
+ g->gray = NULL;
+ g->grayagain = NULL;
+ g->weak = NULL;
+ markobject(g, g->mainthread);
+ /* make global table be traversed before main stack */
+ markvalue(g, gt(g->mainthread));
+ markvalue(g, registry(L));
+ markmt(g);
+ g->gcstate = GCSpropagate;
}
-static size_t mark (lua_State *L) {
- size_t deadmem;
- GCState st;
- GCObject *wkv;
- st.g = G(L);
- st.tmark = NULL;
- st.wkv = st.wk = st.wv = NULL;
- markroot(&st, L);
- propagatemarks(&st); /* mark all reachable objects */
- cleartablevalues(st.wkv);
- cleartablevalues(st.wv);
- wkv = st.wkv; /* keys must be cleared after preserving udata */
- st.wkv = NULL;
- st.wv = NULL;
- deadmem = luaC_separateudata(L); /* separate userdata to be preserved */
- marktmu(&st); /* mark `preserved' userdata */
- deadmem += propagatemarks(&st); /* remark, to propagate `preserveness' */
- cleartablekeys(wkv);
- /* `propagatemarks' may resuscitate some weak tables; clear them too */
- cleartablekeys(st.wk);
- cleartablevalues(st.wv);
- cleartablekeys(st.wkv);
- cleartablevalues(st.wkv);
- return deadmem;
+static void remarkupvals (global_State *g) {
+ UpVal *uv;
+ for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) {
+ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
+ if (isgray(obj2gco(uv)))
+ markvalue(g, uv->v);
+ }
}
-void luaC_collectgarbage (lua_State *L) {
- size_t deadmem = mark(L);
- luaC_sweep(L, 0);
- checkSizes(L, deadmem);
- luaC_callGCTM(L);
+static void atomic (lua_State *L) {
+ global_State *g = G(L);
+ size_t udsize; /* total size of userdata to be finalized */
+ /* remark occasional upvalues of (maybe) dead threads */
+ remarkupvals(g);
+ /* traverse objects cautch by write barrier and by 'remarkupvals' */
+ propagateall(g);
+ /* remark weak tables */
+ g->gray = g->weak;
+ g->weak = NULL;
+ lua_assert(!iswhite(obj2gco(g->mainthread)));
+ markobject(g, L); /* mark running thread */
+ markmt(g); /* mark basic metatables (again) */
+ propagateall(g);
+ /* remark gray again */
+ g->gray = g->grayagain;
+ g->grayagain = NULL;
+ propagateall(g);
+ udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */
+ marktmu(g); /* mark `preserved' userdata */
+ udsize += propagateall(g); /* remark, to propagate `preserveness' */
+ cleartable(g->weak); /* remove collected objects from weak tables */
+ /* flip current white */
+ g->currentwhite = cast_byte(otherwhite(g));
+ g->sweepstrgc = 0;
+ g->sweepgc = &g->rootgc;
+ g->gcstate = GCSsweepstring;
+ g->estimate = g->totalbytes - udsize; /* first estimate */
+}
+
+
+static l_mem singlestep (lua_State *L) {
+ global_State *g = G(L);
+ /*lua_checkmemory(L);*/
+ switch (g->gcstate) {
+ case GCSpause: {
+ markroot(L); /* start a new collection */
+ return 0;
+ }
+ case GCSpropagate: {
+ if (g->gray)
+ return propagatemark(g);
+ else { /* no more `gray' objects */
+ atomic(L); /* finish mark phase */
+ return 0;
+ }
+ }
+ case GCSsweepstring: {
+ lu_mem old = g->totalbytes;
+ sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);
+ if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */
+ g->gcstate = GCSsweep; /* end sweep-string phase */
+ lua_assert(old >= g->totalbytes);
+ g->estimate -= old - g->totalbytes;
+ return GCSWEEPCOST;
+ }
+ case GCSsweep: {
+ lu_mem old = g->totalbytes;
+ g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
+ if (*g->sweepgc == NULL) { /* nothing more to sweep? */
+ checkSizes(L);
+ g->gcstate = GCSfinalize; /* end sweep phase */
+ }
+ lua_assert(old >= g->totalbytes);
+ g->estimate -= old - g->totalbytes;
+ return GCSWEEPMAX*GCSWEEPCOST;
+ }
+ case GCSfinalize: {
+ if (g->tmudata) {
+ GCTM(L);
+ if (g->estimate > GCFINALIZECOST)
+ g->estimate -= GCFINALIZECOST;
+ return GCFINALIZECOST;
+ }
+ else {
+ g->gcstate = GCSpause; /* end collection */
+ g->gcdept = 0;
+ return 0;
+ }
+ }
+ default: lua_assert(0); return 0;
+ }
+}
+
+
+void luaC_step (lua_State *L) {
+ global_State *g = G(L);
+ l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul;
+ if (lim == 0)
+ lim = (MAX_LUMEM-1)/2; /* no limit */
+ g->gcdept += g->totalbytes - g->GCthreshold;
+ do {
+ lim -= singlestep(L);
+ if (g->gcstate == GCSpause)
+ break;
+ } while (lim > 0);
+ if (g->gcstate != GCSpause) {
+ if (g->gcdept < GCSTEPSIZE)
+ g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/
+ else {
+ g->gcdept -= GCSTEPSIZE;
+ g->GCthreshold = g->totalbytes;
+ }
+ }
+ else {
+ lua_assert(g->totalbytes >= g->estimate);
+ setthreshold(g);
+ }
+}
+
+
+void luaC_fullgc (lua_State *L) {
+ global_State *g = G(L);
+ if (g->gcstate <= GCSpropagate) {
+ /* reset sweep marks to sweep all elements (returning them to white) */
+ g->sweepstrgc = 0;
+ g->sweepgc = &g->rootgc;
+ /* reset other collector lists */
+ g->gray = NULL;
+ g->grayagain = NULL;
+ g->weak = NULL;
+ g->gcstate = GCSsweepstring;
+ }
+ lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate);
+ /* finish any pending sweep phase */
+ while (g->gcstate != GCSfinalize) {
+ lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);
+ singlestep(L);
+ }
+ markroot(L);
+ while (g->gcstate != GCSpause) {
+ singlestep(L);
+ }
+ setthreshold(g);
+}
+
+
+void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
+ global_State *g = G(L);
+ lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
+ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
+ lua_assert(ttype(&o->gch) != LUA_TTABLE);
+ /* must keep invariant? */
+ if (g->gcstate == GCSpropagate)
+ reallymarkobject(g, v); /* restore invariant */
+ else /* don't mind */
+ makewhite(g, o); /* mark as white just to avoid other barriers */
+}
+
+
+void luaC_barrierback (lua_State *L, Table *t) {
+ global_State *g = G(L);
+ GCObject *o = obj2gco(t);
+ lua_assert(isblack(o) && !isdead(g, o));
+ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
+ black2gray(o); /* make table gray (again) */
+ t->gclist = g->grayagain;
+ g->grayagain = o;
}
void luaC_link (lua_State *L, GCObject *o, lu_byte tt) {
- o->gch.next = G(L)->rootgc;
- G(L)->rootgc = o;
- o->gch.marked = 0;
+ global_State *g = G(L);
+ o->gch.next = g->rootgc;
+ g->rootgc = o;
+ o->gch.marked = luaC_white(g);
o->gch.tt = tt;
}
+
+void luaC_linkupval (lua_State *L, UpVal *uv) {
+ global_State *g = G(L);
+ GCObject *o = obj2gco(uv);
+ o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */
+ g->rootgc = o;
+ if (isgray(o)) {
+ if (g->gcstate == GCSpropagate) {
+ gray2black(o); /* closed upvalues need barrier */
+ luaC_barrier(L, uv, uv->v);
+ }
+ else { /* sweep phase: sweep it (turning it into white) */
+ makewhite(g, o);
+ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
+ }
+ }
+}
+
diff --git a/lib/lua/src/llex.c b/lib/lua/src/llex.c
index c06ea9f..f48a277 100644
--- a/lib/lua/src/llex.c
+++ b/lib/lua/src/llex.c
@@ -1,14 +1,16 @@
/*
-** $Id: llex.c,v 1.6 2004-12-19 16:14:04 pixel Exp $
+** $Id: llex.c,v 1.7 2007-07-27 10:05:54 pixel Exp $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
#include <ctype.h>
+#include <locale.h>
#include <string.h>
#define llex_c
+#define LUA_CORE
#include "lua.h"
@@ -18,32 +20,54 @@
#include "lparser.h"
#include "lstate.h"
#include "lstring.h"
+#include "ltable.h"
#include "lzio.h"
-#define next(LS) (LS->current = zgetc(LS->z))
+#define next(ls) (ls->current = zgetc(ls->z))
+
+#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r')
+
+
/* ORDER RESERVED */
-static const char *const token2string [] = {
+const char *const luaX_tokens [] = {
"and", "break", "do", "else", "elseif",
"end", "false", "for", "function", "if",
"in", "local", "nil", "not", "or", "repeat",
- "return", "then", "true", "until", "while", "*name",
+ "return", "then", "true", "until", "while",
"..", "...", "==", ">=", "<=", "~=",
- "*number", "*string", "<eof>"
+ "<number>", "<name>", "<string>", "<eof>",
+ NULL
};
+#define save_and_next(ls) (save(ls, ls->current), next(ls))
+
+
+static void save (LexState *ls, int c) {
+ Mbuffer *b = ls->buff;
+ if (b->n + 1 > b->buffsize) {
+ size_t newsize;
+ if (b->buffsize >= MAX_SIZET/2)
+ luaX_lexerror(ls, "lexical element too long", 0);
+ newsize = b->buffsize * 2;
+ luaZ_resizebuffer(ls->L, b, newsize);
+ }
+ b->buffer[b->n++] = cast(char, c);
+}
+
+
void luaX_init (lua_State *L) {
int i;
for (i=0; i<NUM_RESERVED; i++) {
- TString *ts = luaS_new(L, token2string[i]);
+ TString *ts = luaS_new(L, luaX_tokens[i]);
luaS_fix(ts); /* reserved words are never collected */
- lua_assert(strlen(token2string[i])+1 <= TOKEN_LEN);
- ts->tsv.reserved = cast(lu_byte, i+1); /* reserved word */
+ lua_assert(strlen(luaX_tokens[i])+1 <= TOKEN_LEN);
+ ts->tsv.reserved = cast_byte(i+1); /* reserved word */
}
}
@@ -51,85 +75,77 @@ void luaX_init (lua_State *L) {
#define MAXSRC 80
-void luaX_checklimit (LexState *ls, int val, int limit, const char *msg) {
- if (val > limit) {
- msg = luaO_pushfstring(ls->L, "too many %s (limit=%d)", msg, limit);
- luaX_syntaxerror(ls, msg);
+const char *luaX_token2str (LexState *ls, int token) {
+ if (token < FIRST_RESERVED) {
+ lua_assert(token == cast(unsigned char, token));
+ return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) :
+ luaO_pushfstring(ls->L, "%c", token);
}
+ else
+ return luaX_tokens[token-FIRST_RESERVED];
}
-void luaX_errorline (LexState *ls, const char *s, const char *token, int line) {
- lua_State *L = ls->L;
- char buff[MAXSRC];
- luaO_chunkid(buff, getstr(ls->source), MAXSRC);
- luaO_pushfstring(L, "%s:%d: %s near `%s'", buff, line, s, token);
- luaD_throw(L, LUA_ERRSYNTAX);
-}
-
-
-static void luaX_error (LexState *ls, const char *s, const char *token) {
- luaX_errorline(ls, s, token, ls->linenumber);
-}
-
-
-void luaX_syntaxerror (LexState *ls, const char *msg) {
- const char *lasttoken;
- switch (ls->t.token) {
+static const char *txtToken (LexState *ls, int token) {
+ switch (token) {
case TK_NAME:
- lasttoken = getstr(ls->t.seminfo.ts);
- break;
case TK_STRING:
case TK_NUMBER:
- lasttoken = luaZ_buffer(ls->buff);
- break;
+ save(ls, '\0');
+ return luaZ_buffer(ls->buff);
default:
- lasttoken = luaX_token2str(ls, ls->t.token);
- break;
+ return luaX_token2str(ls, token);
}
- luaX_error(ls, msg, lasttoken);
}
-const char *luaX_token2str (LexState *ls, int token) {
- if (token < FIRST_RESERVED) {
- lua_assert(token == (unsigned char)token);
- return luaO_pushfstring(ls->L, "%c", token);
- }
- else
- return token2string[token-FIRST_RESERVED];
+void luaX_lexerror (LexState *ls, const char *msg, int token) {
+ char buff[MAXSRC];
+ luaO_chunkid(buff, getstr(ls->source), MAXSRC);
+ msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg);
+ if (token)
+ luaO_pushfstring(ls->L, "%s near " LUA_QS, msg, txtToken(ls, token));
+ luaD_throw(ls->L, LUA_ERRSYNTAX);
}
-static void luaX_lexerror (LexState *ls, const char *s, int token) {
- if (token == TK_EOS)
- luaX_error(ls, s, luaX_token2str(ls, token));
- else
- luaX_error(ls, s, luaZ_buffer(ls->buff));
+void luaX_syntaxerror (LexState *ls, const char *msg) {
+ luaX_lexerror(ls, msg, ls->t.token);
}
-static void inclinenumber (LexState *LS) {
- next(LS); /* skip `\n' */
- ++LS->linenumber;
- luaX_checklimit(LS, LS->linenumber, MAX_INT, "lines in a chunk");
+TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
+ lua_State *L = ls->L;
+ TString *ts = luaS_newlstr(L, str, l);
+ TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */
+ if (ttisnil(o))
+ setbvalue(o, 1); /* make sure `str' will not be collected */
+ return ts;
}
-void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source) {
- LS->L = L;
- LS->lookahead.token = TK_EOS; /* no look-ahead token */
- LS->z = z;
- LS->fs = NULL;
- LS->linenumber = 1;
- LS->lastline = 1;
- LS->source = source;
- next(LS); /* read first char */
- if (LS->current == '#') {
- do { /* skip first line */
- next(LS);
- } while (LS->current != '\n' && LS->current != EOZ);
- }
+static void inclinenumber (LexState *ls) {
+ int old = ls->current;
+ lua_assert(currIsNewline(ls));
+ next(ls); /* skip `\n' or `\r' */
+ if (currIsNewline(ls) && ls->current != old)
+ next(ls); /* skip `\n\r' or `\r\n' */
+ if (++ls->linenumber >= MAX_INT)
+ luaX_syntaxerror(ls, "chunk has too many lines");
+}
+
+
+void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) {
+ ls->decpoint = '.';
+ ls->L = L;
+ ls->lookahead.token = TK_EOS; /* no look-ahead token */
+ ls->z = z;
+ ls->fs = NULL;
+ ls->linenumber = 1;
+ ls->lastline = 1;
+ ls->source = source;
+ luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */
+ next(ls); /* read first char */
}
@@ -141,269 +157,250 @@ void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source) {
*/
-/* use buffer to store names, literal strings and numbers */
-/* extra space to allocate when growing buffer */
-#define EXTRABUFF 32
+static int check_next (LexState *ls, const char *set) {
+ if (!strchr(set, ls->current))
+ return 0;
+ save_and_next(ls);
+ return 1;
+}
+
-/* maximum number of chars that can be read without checking buffer size */
-#define MAXNOCHECK 5
+static void buffreplace (LexState *ls, char from, char to) {
+ size_t n = luaZ_bufflen(ls->buff);
+ char *p = luaZ_buffer(ls->buff);
+ while (n--)
+ if (p[n] == from) p[n] = to;
+}
-#define checkbuffer(LS, len) \
- if (((len)+MAXNOCHECK)*sizeof(char) > luaZ_sizebuffer((LS)->buff)) \
- luaZ_openspace((LS)->L, (LS)->buff, (len)+EXTRABUFF)
-#define save(LS, c, l) \
- (luaZ_buffer((LS)->buff)[l++] = cast(char, c))
-#define save_and_next(LS, l) (save(LS, LS->current, l), next(LS))
+static void trydecpoint (LexState *ls, SemInfo *seminfo) {
+ /* format error: try to update decimal point separator */
+ struct lconv *cv = localeconv();
+ char old = ls->decpoint;
+ ls->decpoint = (cv ? cv->decimal_point[0] : '.');
+ buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */
+ if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) {
+ /* format error with correct decimal point: no more options */
+ buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */
+ luaX_lexerror(ls, "malformed number", TK_NUMBER);
+ }
+}
-static size_t readname (LexState *LS) {
- size_t l = 0;
- checkbuffer(LS, l);
+/* LUA_NUMBER */
+static void read_numeral (LexState *ls, SemInfo *seminfo) {
+ lua_assert(isdigit(ls->current));
do {
- checkbuffer(LS, l);
- save_and_next(LS, l);
- } while (isalnum(LS->current) || LS->current == '_');
- save(LS, '\0', l);
- return l-1;
+ save_and_next(ls);
+ } while (isdigit(ls->current) || ls->current == '.');
+ if (check_next(ls, "Ee")) /* `E'? */
+ check_next(ls, "+-"); /* optional exponent sign */
+ while (isalnum(ls->current) || ls->current == '_')
+ save_and_next(ls);
+ save(ls, '\0');
+ buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */
+ if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */
+ trydecpoint(ls, seminfo); /* try to update decimal point separator */
}
-/* LUA_NUMBER */
-static void read_numeral (LexState *LS, int comma, SemInfo *seminfo) {
- int oct = 0, hex = 0;
- size_t l = 0;
- checkbuffer(LS, l);
- if (comma) save(LS, '.', l);
- else if (LS->current == '0') {
- oct = 1;
- checkbuffer(LS, 1);
- save_and_next(LS, l);
- if (LS->current == 'x') {
- oct = 0;
- hex = 1;
- checkbuffer(LS, 1);
- save_and_next(LS, l);
- } else if (LS->current == '.') {
- oct = hex = 0;
- }
- }
- while (isdigit(LS->current) || (hex && isxdigit(LS->current))) {
- checkbuffer(LS, l);
- save_and_next(LS, l);
- }
- checkbuffer(LS, 1);
- if (LS->current == '.') {
- save_and_next(LS, l);
- if (hex || oct) {
- save(LS, '\0', l);
- luaX_lexerror(LS,
- "error in number, mixing decimal point with octal or hexadecimal",
- TK_NUMBER);
- }
- if (LS->current == '.') {
- save_and_next(LS, l);
- save(LS, '\0', l);
- luaX_lexerror(LS,
- "ambiguous syntax (decimal point x string concatenation)",
- TK_NUMBER);
- }
- }
- while (isdigit(LS->current)) {
- checkbuffer(LS, l);
- save_and_next(LS, l);
+static int skip_sep (LexState *ls) {
+ int count = 0;
+ int s = ls->current;
+ lua_assert(s == '[' || s == ']');
+ save_and_next(ls);
+ while (ls->current == '=') {
+ save_and_next(ls);
+ count++;
}
- if (LS->current == 'e' || LS->current == 'E') {
- save_and_next(LS, l); /* read `E' */
- if (hex || oct) {
- save(LS, '\0', l);
- luaX_lexerror(LS,
- "error in number, mixing exponential with octal or hexadecimal",
- TK_NUMBER);
- }
- if (LS->current == '+' || LS->current == '-')
- save_and_next(LS, l); /* optional exponent sign */
- while (isdigit(LS->current)) {
- checkbuffer(LS, l);
- save_and_next(LS, l);
- }
- }
- save(LS, '\0', l);
- if (!luaO_str2d(luaZ_buffer(LS->buff), &seminfo->r))
- luaX_lexerror(LS, "malformed number", TK_NUMBER);
+ return (ls->current == s) ? count : (-count) - 1;
}
-static void read_long_string (LexState *LS, SemInfo *seminfo) {
+static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {
int cont = 0;
- size_t l = 0;
- checkbuffer(LS, l);
- save(LS, '[', l); /* save first `[' */
- save_and_next(LS, l); /* pass the second `[' */
- if (LS->current == '\n') /* string starts with a newline? */
- inclinenumber(LS); /* skip it */
+ (void)(cont); /* avoid warnings when `cont' is not used */
+ save_and_next(ls); /* skip 2nd `[' */
+ if (currIsNewline(ls)) /* string starts with a newline? */
+ inclinenumber(ls); /* skip it */
for (;;) {
- checkbuffer(LS, l);
- switch (LS->current) {
+ switch (ls->current) {
case EOZ:
- save(LS, '\0', l);
- luaX_lexerror(LS, (seminfo) ? "unfinished long string" :
+ luaX_lexerror(ls, (seminfo) ? "unfinished long string" :
"unfinished long comment", TK_EOS);
break; /* to avoid warnings */
- case '[':
- save_and_next(LS, l);
- if (LS->current == '[') {
+#if defined(LUA_COMPAT_LSTR)
+ case '[': {
+ if (skip_sep(ls) == sep) {
+ save_and_next(ls); /* skip 2nd `[' */
cont++;
- save_and_next(LS, l);
+#if LUA_COMPAT_LSTR == 1
+ if (sep == 0)
+ luaX_lexerror(ls, "nesting of [[...]] is deprecated", '[');
+#endif
}
- continue;
- case ']':
- save_and_next(LS, l);
- if (LS->current == ']') {
- if (cont == 0) goto endloop;
+ break;
+ }
+#endif
+ case ']': {
+ if (skip_sep(ls) == sep) {
+ save_and_next(ls); /* skip 2nd `]' */
+#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2
cont--;
- save_and_next(LS, l);
+ if (sep == 0 && cont >= 0) break;
+#endif
+ goto endloop;
}
- continue;
+ break;
+ }
case '\n':
- save(LS, '\n', l);
- inclinenumber(LS);
- if (!seminfo) l = 0; /* reset buffer to avoid wasting space */
- continue;
- default:
- save_and_next(LS, l);
+ case '\r': {
+ save(ls, '\n');
+ inclinenumber(ls);
+ if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */
+ break;
+ }
+ default: {
+ if (seminfo) save_and_next(ls);
+ else next(ls);
+ }
}
} endloop:
- save_and_next(LS, l); /* skip the second `]' */
- save(LS, '\0', l);
if (seminfo)
- seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 2, l - 5);
+ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep),
+ luaZ_bufflen(ls->buff) - 2*(2 + sep));
}
-static void read_string (LexState *LS, int del, SemInfo *seminfo) {
- size_t l = 0;
- checkbuffer(LS, l);
- save_and_next(LS, l);
- while (LS->current != del) {
- checkbuffer(LS, l);
- switch (LS->current) {
+static void read_string (LexState *ls, int del, SemInfo *seminfo) {
+ save_and_next(ls);
+ while (ls->current != del) {
+ switch (ls->current) {
case EOZ:
- save(LS, '\0', l);
- luaX_lexerror(LS, "unfinished string", TK_EOS);
- break; /* to avoid warnings */
+ luaX_lexerror(ls, "unfinished string", TK_EOS);
+ continue; /* to avoid warnings */
case '\n':
- save(LS, '\0', l);
- luaX_lexerror(LS, "unfinished string", TK_STRING);
- break; /* to avoid warnings */
- case '\\':
- next(LS); /* do not save the `\' */
- switch (LS->current) {
- case 'a': save(LS, '\a', l); next(LS); break;
- case 'b': save(LS, '\b', l); next(LS); break;
- case 'f': save(LS, '\f', l); next(LS); break;
- case 'n': save(LS, '\n', l); next(LS); break;
- case 'r': save(LS, '\r', l); next(LS); break;
- case 't': save(LS, '\t', l); next(LS); break;
- case 'v': save(LS, '\v', l); next(LS); break;
- case '\n': save(LS, '\n', l); inclinenumber(LS); break;
- case EOZ: break; /* will raise an error next loop */
+ case '\r':
+ luaX_lexerror(ls, "unfinished string", TK_STRING);
+ continue; /* to avoid warnings */
+ case '\\': {
+ int c;
+ next(ls); /* do not save the `\' */
+ switch (ls->current) {
+ case 'a': c = '\a'; break;
+ case 'b': c = '\b'; break;
+ case 'f': c = '\f'; break;
+ case 'n': c = '\n'; break;
+ case 'r': c = '\r'; break;
+ case 't': c = '\t'; break;
+ case 'v': c = '\v'; break;
+ case '\n': /* go through */
+ case '\r': save(ls, '\n'); inclinenumber(ls); continue;
+ case EOZ: continue; /* will raise an error next loop */
default: {
- if (!isdigit(LS->current))
- save_and_next(LS, l); /* handles \\, \", \', and \? */
+ if (!isdigit(ls->current))
+ save_and_next(ls); /* handles \\, \", \', and \? */
else { /* \xxx */
- int c = 0;
int i = 0;
+ c = 0;
do {
- c = 10*c + (LS->current-'0');
- next(LS);
- } while (++i<3 && isdigit(LS->current));
- if (c > UCHAR_MAX) {
- save(LS, '\0', l);
- luaX_lexerror(LS, "escape sequence too large", TK_STRING);
- }
- save(LS, c, l);
+ c = 10*c + (ls->current-'0');
+ next(ls);
+ } while (++i<3 && isdigit(ls->current));
+ if (c > UCHAR_MAX)
+ luaX_lexerror(ls, "escape sequence too large", TK_STRING);
+ save(ls, c);
}
+ continue;
}
}
- break;
+ save(ls, c);
+ next(ls);
+ continue;
+ }
default:
- save_and_next(LS, l);
+ save_and_next(ls);
}
}
- save_and_next(LS, l); /* skip delimiter */
- save(LS, '\0', l);
- seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 1, l - 3);
+ save_and_next(ls); /* skip delimiter */
+ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1,
+ luaZ_bufflen(ls->buff) - 2);
}
-int luaX_lex (LexState *LS, SemInfo *seminfo) {
+static int llex (LexState *ls, SemInfo *seminfo) {
+ luaZ_resetbuffer(ls->buff);
for (;;) {
- switch (LS->current) {
-
- case '\n': {
- inclinenumber(LS);
+ switch (ls->current) {
+ case '\n':
+ case '\r': {
+ inclinenumber(ls);
continue;
}
case '-': {
- next(LS);
- if (LS->current != '-') return '-';
+ next(ls);
+ if (ls->current != '-') return '-';
/* else is a comment */
- next(LS);
- if (LS->current == '[' && (next(LS), LS->current == '['))
- read_long_string(LS, NULL); /* long comment */
- else /* short comment */
- while (LS->current != '\n' && LS->current != EOZ)
- next(LS);
+ next(ls);
+ if (ls->current == '[') {
+ int sep = skip_sep(ls);
+ luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */
+ if (sep >= 0) {
+ read_long_string(ls, NULL, sep); /* long comment */
+ luaZ_resetbuffer(ls->buff);
+ continue;
+ }
+ }
+ /* else short comment */
+ while (!currIsNewline(ls) && ls->current != EOZ)
+ next(ls);
continue;
}
case '[': {
- next(LS);
- if (LS->current != '[') return '[';
- else {
- read_long_string(LS, seminfo);
+ int sep = skip_sep(ls);
+ if (sep >= 0) {
+ read_long_string(ls, seminfo, sep);
return TK_STRING;
}
+ else if (sep == -1) return '[';
+ else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING);
}
case '=': {
- next(LS);
- if (LS->current != '=') return '=';
- else { next(LS); return TK_EQ; }
+ next(ls);
+ if (ls->current != '=') return '=';
+ else { next(ls); return TK_EQ; }
}
case '<': {
- next(LS);
- if (LS->current != '=') return '<';
- else { next(LS); return TK_LE; }
+ next(ls);
+ if (ls->current != '=') return '<';
+ else { next(ls); return TK_LE; }
}
case '>': {
- next(LS);
- if (LS->current != '=') return '>';
- else { next(LS); return TK_GE; }
+ next(ls);
+ if (ls->current != '=') return '>';
+ else { next(ls); return TK_GE; }
}
case '~': {
- next(LS);
- if (LS->current != '=') return '~';
- else { next(LS); return TK_NE; }
+ next(ls);
+ if (ls->current != '=') return '~';
+ else { next(ls); return TK_NE; }
}
case '"':
case '\'': {
- read_string(LS, LS->current, seminfo);
+ read_string(ls, ls->current, seminfo);
return TK_STRING;
}
case '.': {
- next(LS);
- if (LS->current == '.') {
- next(LS);
- if (LS->current == '.') {
- next(LS);
+ save_and_next(ls);
+ if (check_next(ls, ".")) {
+ if (check_next(ls, "."))
return TK_DOTS; /* ... */
- }
else return TK_CONCAT; /* .. */
}
- else if (!isdigit(LS->current)) return '.';
+ else if (!isdigit(ls->current)) return '.';
else {
- read_numeral(LS, 1, seminfo);
+ read_numeral(ls, seminfo);
return TK_NUMBER;
}
}
@@ -411,29 +408,33 @@ int luaX_lex (LexState *LS, SemInfo *seminfo) {
return TK_EOS;
}
default: {
- if (isspace(LS->current)) {
- next(LS);
+ if (isspace(ls->current)) {
+ lua_assert(!currIsNewline(ls));
+ next(ls);
continue;
}
- else if (isdigit(LS->current)) {
- read_numeral(LS, 0, seminfo);
+ else if (isdigit(ls->current)) {
+ read_numeral(ls, seminfo);
return TK_NUMBER;
}
- else if (isalpha(LS->current) || LS->current == '_') {
+ else if (isalpha(ls->current) || ls->current == '_') {
/* identifier or reserved word */
- size_t l = readname(LS);
- TString *ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff), l);
+ TString *ts;
+ do {
+ save_and_next(ls);
+ } while (isalnum(ls->current) || ls->current == '_');
+ ts = luaX_newstring(ls, luaZ_buffer(ls->buff),
+ luaZ_bufflen(ls->buff));
if (ts->tsv.reserved > 0) /* reserved word? */
return ts->tsv.reserved - 1 + FIRST_RESERVED;
- seminfo->ts = ts;
- return TK_NAME;
+ else {
+ seminfo->ts = ts;
+ return TK_NAME;
+ }
}
else {
- int c = LS->current;
- if (iscntrl(c))
- luaX_error(LS, "invalid control char",
- luaO_pushfstring(LS->L, "char(%d)", c));
- next(LS);
+ int c = ls->current;
+ next(ls);
return c; /* single-char tokens (+ - / ...) */
}
}
@@ -441,4 +442,20 @@ int luaX_lex (LexState *LS, SemInfo *seminfo) {
}
}
-#undef next
+
+void luaX_next (LexState *ls) {
+ ls->lastline = ls->linenumber;
+ if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */
+ ls->t = ls->lookahead; /* use this one */
+ ls->lookahead.token = TK_EOS; /* and discharge it */
+ }
+ else
+ ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */
+}
+
+
+void luaX_lookahead (LexState *ls) {
+ lua_assert(ls->lookahead.token == TK_EOS);
+ ls->lookahead.token = llex(ls, &ls->lookahead.seminfo);
+}
+
diff --git a/lib/lua/src/lmem.c b/lib/lua/src/lmem.c
index b10ec3f..c95d1c3 100644
--- a/lib/lua/src/lmem.c
+++ b/lib/lua/src/lmem.c
@@ -1,13 +1,14 @@
/*
-** $Id: lmem.c,v 1.4 2004-11-27 21:46:07 pixel Exp $
+** $Id: lmem.c,v 1.5 2007-07-27 10:05:54 pixel Exp $
** Interface to Memory Manager
** See Copyright Notice in lua.h
*/
-#include <stdlib.h>
+#include <stddef.h>
#define lmem_c
+#define LUA_CORE
#include "lua.h"
@@ -20,72 +21,66 @@
/*
-** definition for realloc function. It must assure that l_realloc(NULL,
-** 0, x) allocates a new block (ANSI C assures that). (`os' is the old
-** block size; some allocators may use that.)
+** About the realloc function:
+** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize);
+** (`osize' is the old size, `nsize' is the new size)
+**
+** Lua ensures that (ptr == NULL) iff (osize == 0).
+**
+** * frealloc(ud, NULL, 0, x) creates a new block of size `x'
+**
+** * frealloc(ud, p, x, 0) frees the block `p'
+** (in this specific case, frealloc must return NULL).
+** particularly, frealloc(ud, NULL, 0, 0) does nothing
+** (which is equivalent to free(NULL) in ANSI C)
+**
+** frealloc returns NULL if it cannot create or reallocate the area
+** (any reallocation to an equal or smaller size cannot fail!)
*/
-#ifndef l_realloc
-#define l_realloc(b,os,s) realloc(b,s)
-#endif
-/*
-** definition for free function. (`os' is the old block size; some
-** allocators may use that.)
-*/
-#ifndef l_free
-#define l_free(b,os) free(b)
-#endif
#define MINSIZEARRAY 4
-void *luaM_growaux (lua_State *L, void *block, int *size, int size_elems,
- int limit, const char *errormsg) {
+void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems,
+ int limit, const char *errormsg) {
void *newblock;
- int newsize = (*size)*2;
- if (newsize < MINSIZEARRAY)
- newsize = MINSIZEARRAY; /* minimum size */
- else if (*size >= limit/2) { /* cannot double it? */
- if (*size < limit - MINSIZEARRAY) /* try something smaller... */
- newsize = limit; /* still have at least MINSIZEARRAY free places */
- else luaG_runerror(L, errormsg);
+ int newsize;
+ if (*size >= limit/2) { /* cannot double it? */
+ if (*size >= limit) /* cannot grow even a little? */
+ luaG_runerror(L, errormsg);
+ newsize = limit; /* still have at least one free place */
+ }
+ else {
+ newsize = (*size)*2;
+ if (newsize < MINSIZEARRAY)
+ newsize = MINSIZEARRAY; /* minimum size */
}
- newblock = luaM_realloc(L, block,
- cast(lu_mem, *size)*cast(lu_mem, size_elems),
- cast(lu_mem, newsize)*cast(lu_mem, size_elems));
+ newblock = luaM_reallocv(L, block, *size, newsize, size_elems);
*size = newsize; /* update only when everything else is OK */
return newblock;
}
+void *luaM_toobig (lua_State *L) {
+ luaG_runerror(L, "memory allocation error: block too big");
+ return NULL; /* to avoid warnings */
+}
+
+
+
/*
** generic allocation routine.
*/
-void *luaM_realloc (lua_State *L, void *block, lu_mem oldsize, lu_mem size) {
- lua_assert((oldsize == 0) == (block == NULL));
- if (size == 0) {
- if (block != NULL) {
- l_free(block, oldsize);
- block = NULL;
- }
- else return NULL; /* avoid `nblocks' computations when oldsize==size==0 */
- }
- else if (size >= MAX_SIZET)
- luaG_runerror(L, "memory allocation error: block too big");
- else {
- block = l_realloc(block, oldsize, size);
- if (block == NULL) {
- if (L)
- luaD_throw(L, LUA_ERRMEM);
- else return NULL; /* error before creating state! */
- }
- }
- if (L) {
- lua_assert(G(L) != NULL && G(L)->nblocks > 0);
- G(L)->nblocks -= oldsize;
- G(L)->nblocks += size;
- }
+void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
+ global_State *g = G(L);
+ lua_assert((osize == 0) == (block == NULL));
+ block = (*g->frealloc)(g->ud, block, osize, nsize);
+ if (block == NULL && nsize > 0)
+ luaD_throw(L, LUA_ERRMEM);
+ lua_assert((nsize == 0) == (block == NULL));
+ g->totalbytes = (g->totalbytes - osize) + nsize;
return block;
}
diff --git a/lib/lua/src/lobject.c b/lib/lua/src/lobject.c
index 62c70b6..0bfc9be 100644
--- a/lib/lua/src/lobject.c
+++ b/lib/lua/src/lobject.c
@@ -1,15 +1,17 @@
/*
-** $Id: lobject.c,v 1.6 2004-12-19 16:14:04 pixel Exp $
+** $Id: lobject.c,v 1.7 2007-07-27 10:05:54 pixel Exp $
** Some generic functions over Lua objects
** See Copyright Notice in lua.h
*/
#include <ctype.h>
#include <stdarg.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define lobject_c
+#define LUA_CORE
#include "lua.h"
@@ -20,57 +22,60 @@
#include "lstring.h"
#include "lvm.h"
-const TObject luaO_nilobject = {LUA_TNIL, {NULL}};
+
+
+const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL};
/*
** converts an integer to a "floating point byte", represented as
-** (mmmmmxxx), where the real value is (xxx) * 2^(mmmmm)
+** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if
+** eeeee != 0 and (xxx) otherwise.
*/
int luaO_int2fb (unsigned int x) {
- int m = 0; /* mantissa */
- while (x >= (1<<3)) {
+ int e = 0; /* expoent */
+ while (x >= 16) {
x = (x+1) >> 1;
- m++;
+ e++;
}
- return (m << 3) | cast(int, x);
+ if (x < 8) return x;
+ else return ((e+1) << 3) | (cast_int(x) - 8);
+}
+
+
+/* converts back */
+int luaO_fb2int (int x) {
+ int e = (x >> 3) & 31;
+ if (e == 0) return x;
+ else return ((x & 7)+8) << (e - 1);
}
int luaO_log2 (unsigned int x) {
- static const lu_byte log_8[255] = {
- 0,
- 1,1,
- 2,2,2,2,
- 3,3,3,3,3,3,3,3,
- 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
- 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ static const lu_byte log_2[256] = {
+ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
};
- if (x >= 0x00010000) {
- if (x >= 0x01000000) return log_8[((x>>24) & 0xff) - 1]+24;
- else return log_8[((x>>16) & 0xff) - 1]+16;
- }
- else {
- if (x >= 0x00000100) return log_8[((x>>8) & 0xff) - 1]+8;
- else if (x) return log_8[(x & 0xff) - 1];
- return -1; /* special `log' for 0 */
- }
+ int l = -1;
+ while (x >= 256) { l += 8; x >>= 8; }
+ return l + log_2[x];
+
}
-int luaO_rawequalObj (const TObject *t1, const TObject *t2) {
+int luaO_rawequalObj (const TValue *t1, const TValue *t2) {
if (ttype(t1) != ttype(t2)) return 0;
else switch (ttype(t1)) {
case LUA_TNIL:
return 1;
case LUA_TNUMBER:
- return nvalue(t1) == nvalue(t2);
+ return luai_numeq(nvalue(t1), nvalue(t2));
case LUA_TBOOLEAN:
return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */
case LUA_TLIGHTUSERDATA:
@@ -84,45 +89,40 @@ int luaO_rawequalObj (const TObject *t1, const TObject *t2) {
int luaO_str2d (const char *s, lua_Number *result) {
char *endptr;
- size_t l = strlen(s);
- lua_Number res;
- if ((l > 0) && (s[0] == '0') && (s[1] != '.')) {
- if ((l > 2) && (s[1] == 'x')) {
- res = strtol(s + 2, &endptr, 16);
- } else {
- res = strtol(s + 1, &endptr, 8);
- }
- } else {
- res = strtod(s, &endptr);
- }
- if (endptr == s) return 0; /* no conversion */
- while (isspace((unsigned char)(*endptr))) endptr++;
+ *result = lua_str2number(s, &endptr);
+ if (endptr == s) return 0; /* conversion failed */
+ if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */
+ *result = cast_num(strtoul(s, &endptr, 16));
+ if (*endptr == '\0') return 1; /* most common case */
+ while (isspace(cast(unsigned char, *endptr))) endptr++;
if (*endptr != '\0') return 0; /* invalid trailing characters? */
- *result = res;
return 1;
}
static void pushstr (lua_State *L, const char *str) {
- setsvalue2s(L->top, luaS_new(L, str));
+ setsvalue2s(L, L->top, luaS_new(L, str));
incr_top(L);
}
-/* this function handles only `%d', `%c', %f, and `%s' formats */
+/* this function handles only `%d', `%c', %f, %p, and `%s' formats */
const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
int n = 1;
pushstr(L, "");
for (;;) {
const char *e = strchr(fmt, '%');
if (e == NULL) break;
- setsvalue2s(L->top, luaS_newlstr(L, fmt, e-fmt));
+ setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt));
incr_top(L);
switch (*(e+1)) {
- case 's':
- pushstr(L, va_arg(argp, char *));
+ case 's': {
+ const char *s = va_arg(argp, char *);
+ if (s == NULL) s = "(null)";
+ pushstr(L, s);
break;
+ }
case 'c': {
char buff[2];
buff[0] = cast(char, va_arg(argp, int));
@@ -130,24 +130,40 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
pushstr(L, buff);
break;
}
- case 'd':
- setnvalue(L->top, cast(lua_Number, va_arg(argp, int)));
+ case 'd': {
+ setnvalue(L->top, cast_num(va_arg(argp, int)));
incr_top(L);
break;
- case 'f':
- setnvalue(L->top, cast(lua_Number, va_arg(argp, l_uacNumber)));
+ }
+ case 'f': {
+ setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber)));
incr_top(L);
break;
- case '%':
+ }
+ case 'p': {
+ char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */
+ sprintf(buff, "%p", va_arg(argp, void *));
+ pushstr(L, buff);
+ break;
+ }
+ case '%': {
pushstr(L, "%");
break;
- default: lua_assert(0);
+ }
+ default: {
+ char buff[3];
+ buff[0] = '%';
+ buff[1] = *(e+1);
+ buff[2] = '\0';
+ pushstr(L, buff);
+ break;
+ }
}
n += 2;
fmt = e+2;
}
pushstr(L, fmt);
- luaV_concat(L, n+1, L->top - L->base - 1);
+ luaV_concat(L, n+1, cast_int(L->top - L->base) - 1);
L->top -= n;
return svalue(L->top - 1);
}
@@ -163,26 +179,26 @@ const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) {
}
-void luaO_chunkid (char *out, const char *source, int bufflen) {
+void luaO_chunkid (char *out, const char *source, size_t bufflen) {
if (*source == '=') {
strncpy(out, source+1, bufflen); /* remove first char */
out[bufflen-1] = '\0'; /* ensures null termination */
}
else { /* out = "source", or "...source" */
if (*source == '@') {
- int l;
+ size_t l;
source++; /* skip the `@' */
- bufflen -= sizeof(" `...' ");
+ bufflen -= sizeof(" '...' ");
l = strlen(source);
strcpy(out, "");
- if (l>bufflen) {
+ if (l > bufflen) {
source += (l-bufflen); /* get last part of file name */
strcat(out, "...");
}
strcat(out, source);
}
else { /* out = [string "string"] */
- int len = strcspn(source, "\n"); /* stop at first newline */
+ size_t len = strcspn(source, "\n\r"); /* stop at first newline */
bufflen -= sizeof(" [string \"...\"] ");
if (len > bufflen) len = bufflen;
strcpy(out, "[string \"");
diff --git a/lib/lua/src/lopcodes.c b/lib/lua/src/lopcodes.c
index c018ea8..a38e405 100644
--- a/lib/lua/src/lopcodes.c
+++ b/lib/lua/src/lopcodes.c
@@ -1,22 +1,19 @@
/*
-** $Id: lopcodes.c,v 1.4 2004-11-27 21:46:07 pixel Exp $
-** extracted automatically from lopcodes.h by mkprint.lua
-** DO NOT EDIT
+** $Id: lopcodes.c,v 1.5 2007-07-27 10:05:54 pixel Exp $
** See Copyright Notice in lua.h
*/
#define lopcodes_c
+#define LUA_CORE
-#include "lua.h"
-#include "lobject.h"
#include "lopcodes.h"
-#ifdef LUA_OPNAMES
+/* ORDER OP */
-const char *const luaP_opnames[] = {
+const char *const luaP_opnames[NUM_OPCODES+1] = {
"MOVE",
"LOADK",
"LOADBOOL",
@@ -33,70 +30,73 @@ const char *const luaP_opnames[] = {
"SUB",
"MUL",
"DIV",
+ "MOD",
"POW",
"UNM",
"NOT",
+ "LEN",
"CONCAT",
"JMP",
"EQ",
"LT",
"LE",
"TEST",
+ "TESTSET",
"CALL",
"TAILCALL",
"RETURN",
"FORLOOP",
+ "FORPREP",
"TFORLOOP",
- "TFORPREP",
"SETLIST",
- "SETLISTO",
"CLOSE",
- "CLOSURE"
+ "CLOSURE",
+ "VARARG",
+ NULL
};
-#endif
-
-#define opmode(t,b,bk,ck,sa,k,m) (((t)<<OpModeT) | \
- ((b)<<OpModeBreg) | ((bk)<<OpModeBrk) | ((ck)<<OpModeCrk) | \
- ((sa)<<OpModesetA) | ((k)<<OpModeK) | (m))
+#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m))
const lu_byte luaP_opmodes[NUM_OPCODES] = {
-/* T B Bk Ck sA K mode opcode */
- opmode(0, 1, 0, 0, 1, 0, iABC) /* OP_MOVE */
- ,opmode(0, 0, 0, 0, 1, 1, iABx) /* OP_LOADK */
- ,opmode(0, 0, 0, 0, 1, 0, iABC) /* OP_LOADBOOL */
- ,opmode(0, 1, 0, 0, 1, 0, iABC) /* OP_LOADNIL */
- ,opmode(0, 0, 0, 0, 1, 0, iABC) /* OP_GETUPVAL */
- ,opmode(0, 0, 0, 0, 1, 1, iABx) /* OP_GETGLOBAL */
- ,opmode(0, 1, 0, 1, 1, 0, iABC) /* OP_GETTABLE */
- ,opmode(0, 0, 0, 0, 0, 1, iABx) /* OP_SETGLOBAL */
- ,opmode(0, 0, 0, 0, 0, 0, iABC) /* OP_SETUPVAL */
- ,opmode(0, 0, 1, 1, 0, 0, iABC) /* OP_SETTABLE */
- ,opmode(0, 0, 0, 0, 1, 0, iABC) /* OP_NEWTABLE */
- ,opmode(0, 1, 0, 1, 1, 0, iABC) /* OP_SELF */
- ,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_ADD */
- ,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_SUB */
- ,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_MUL */
- ,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_DIV */
- ,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_POW */
- ,opmode(0, 1, 0, 0, 1, 0, iABC) /* OP_UNM */
- ,opmode(0, 1, 0, 0, 1, 0, iABC) /* OP_NOT */
- ,opmode(0, 1, 0, 1, 1, 0, iABC) /* OP_CONCAT */
- ,opmode(0, 0, 0, 0, 0, 0, iAsBx) /* OP_JMP */
- ,opmode(1, 0, 1, 1, 0, 0, iABC) /* OP_EQ */
- ,opmode(1, 0, 1, 1, 0, 0, iABC) /* OP_LT */
- ,opmode(1, 0, 1, 1, 0, 0, iABC) /* OP_LE */
- ,opmode(1, 1, 0, 0, 1, 0, iABC) /* OP_TEST */
- ,opmode(0, 0, 0, 0, 0, 0, iABC) /* OP_CALL */
- ,opmode(0, 0, 0, 0, 0, 0, iABC) /* OP_TAILCALL */
- ,opmode(0, 0, 0, 0, 0, 0, iABC) /* OP_RETURN */
- ,opmode(0, 0, 0, 0, 0, 0, iAsBx) /* OP_FORLOOP */
- ,opmode(1, 0, 0, 0, 0, 0, iABC) /* OP_TFORLOOP */
- ,opmode(0, 0, 0, 0, 0, 0, iAsBx) /* OP_TFORPREP */
- ,opmode(0, 0, 0, 0, 0, 0, iABx) /* OP_SETLIST */
- ,opmode(0, 0, 0, 0, 0, 0, iABx) /* OP_SETLISTO */
- ,opmode(0, 0, 0, 0, 0, 0, iABC) /* OP_CLOSE */
- ,opmode(0, 0, 0, 0, 1, 0, iABx) /* OP_CLOSURE */
+/* T A B C mode opcode */
+ opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */
+ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */
+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */
+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */
+ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */
+ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */
+ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */
+ ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */
+ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */
+ ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */
+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */
+ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */
+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */
+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */
+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */
+ ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */
+ ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */
+ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */
+ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */
+ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */
+ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */
+ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */
+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */
+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */
+ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */
+ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */
+ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */
+ ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */
+ ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */
+ ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */
+ ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */
+ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */
};
diff --git a/lib/lua/src/lparser.c b/lib/lua/src/lparser.c
index 227e27a..206364a 100644
--- a/lib/lua/src/lparser.c
+++ b/lib/lua/src/lparser.c
@@ -1,5 +1,5 @@
/*
-** $Id: lparser.c,v 1.6 2005-01-02 05:01:17 pixel Exp $
+** $Id: lparser.c,v 1.7 2007-07-27 10:05:54 pixel Exp $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -8,11 +8,13 @@
#include <string.h>
#define lparser_c
+#define LUA_CORE
#include "lua.h"
#include "lcode.h"
#include "ldebug.h"
+#include "ldo.h"
#include "lfunc.h"
#include "llex.h"
#include "lmem.h"
@@ -21,16 +23,15 @@
#include "lparser.h"
#include "lstate.h"
#include "lstring.h"
+#include "ltable.h"
+#define hasmultret(k) ((k) == VCALL || (k) == VVARARG)
#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]])
-
-#define enterlevel(ls) if (++(ls)->nestlevel > LUA_MAXPARSERLEVEL) \
- luaX_syntaxerror(ls, "too many syntax levels");
-#define leavelevel(ls) ((ls)->nestlevel--)
+#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m)
/*
@@ -39,9 +40,9 @@
typedef struct BlockCnt {
struct BlockCnt *previous; /* chain */
int breaklist; /* list of jumps out of this loop */
- int nactvar; /* # active local variables outside the breakable structure */
- int upval; /* true if some variable in the block is an upvalue */
- int isbreakable; /* true if `block' is a loop */
+ lu_byte nactvar; /* # active locals outside the breakable structure */
+ lu_byte upval; /* true if some variable in the block is an upvalue */
+ lu_byte isbreakable; /* true if `block' is a loop */
} BlockCnt;
@@ -53,33 +54,32 @@ static void chunk (LexState *ls);
static void expr (LexState *ls, expdesc *v);
-
-static void next (LexState *ls) {
- ls->lastline = ls->linenumber;
- if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */
- ls->t = ls->lookahead; /* use this one */
- ls->lookahead.token = TK_EOS; /* and discharge it */
+static void anchor_token (LexState *ls) {
+ if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) {
+ TString *ts = ls->t.seminfo.ts;
+ luaX_newstring(ls, getstr(ts), ts->tsv.len);
}
- else
- ls->t.token = luaX_lex(ls, &ls->t.seminfo); /* read next token */
}
-static void lookahead (LexState *ls) {
- lua_assert(ls->lookahead.token == TK_EOS);
- ls->lookahead.token = luaX_lex(ls, &ls->lookahead.seminfo);
+static void error_expected (LexState *ls, int token) {
+ luaX_syntaxerror(ls,
+ luaO_pushfstring(ls->L, LUA_QS " expected", luaX_token2str(ls, token)));
}
-static void error_expected (LexState *ls, int token) {
- luaX_syntaxerror(ls,
- luaO_pushfstring(ls->L, "`%s' expected", luaX_token2str(ls, token)));
+static void errorlimit (FuncState *fs, int limit, const char *what) {
+ const char *msg = (fs->f->linedefined == 0) ?
+ luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) :
+ luaO_pushfstring(fs->L, "function at line %d has more than %d %s",
+ fs->f->linedefined, limit, what);
+ luaX_lexerror(fs->ls, msg, 0);
}
static int testnext (LexState *ls, int c) {
if (ls->t.token == c) {
- next(ls);
+ luaX_next(ls);
return 1;
}
else return 0;
@@ -87,10 +87,15 @@ static int testnext (LexState *ls, int c) {
static void check (LexState *ls, int c) {
- if (!testnext(ls, c))
+ if (ls->t.token != c)
error_expected(ls, c);
}
+static void checknext (LexState *ls, int c) {
+ check(ls, c);
+ luaX_next(ls);
+}
+
#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); }
@@ -102,7 +107,7 @@ static void check_match (LexState *ls, int what, int who, int where) {
error_expected(ls, what);
else {
luaX_syntaxerror(ls, luaO_pushfstring(ls->L,
- "`%s' expected (to close `%s' at line %d)",
+ LUA_QS " expected (to close " LUA_QS " at line %d)",
luaX_token2str(ls, what), luaX_token2str(ls, who), where));
}
}
@@ -111,9 +116,9 @@ static void check_match (LexState *ls, int what, int who, int where) {
static TString *str_checkname (LexState *ls) {
TString *ts;
- check_condition(ls, (ls->t.token == TK_NAME), "<name> expected");
+ check(ls, TK_NAME);
ts = ls->t.seminfo.ts;
- next(ls);
+ luaX_next(ls);
return ts;
}
@@ -121,7 +126,7 @@ static TString *str_checkname (LexState *ls) {
static void init_exp (expdesc *e, expkind k, int i) {
e->f = e->t = NO_JUMP;
e->k = k;
- e->info = i;
+ e->u.s.info = i;
}
@@ -135,26 +140,33 @@ static void checkname(LexState *ls, expdesc *e) {
}
-static int luaI_registerlocalvar (LexState *ls, TString *varname) {
+static int registerlocalvar (LexState *ls, TString *varname) {
FuncState *fs = ls->fs;
Proto *f = fs->f;
+ int oldsize = f->sizelocvars;
luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars,
- LocVar, MAX_INT, "");
+ LocVar, SHRT_MAX, "too many local variables");
+ while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL;
f->locvars[fs->nlocvars].varname = varname;
+ luaC_objbarrier(ls->L, f, varname);
return fs->nlocvars++;
}
+#define new_localvarliteral(ls,v,n) \
+ new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n)
+
+
static void new_localvar (LexState *ls, TString *name, int n) {
FuncState *fs = ls->fs;
- luaX_checklimit(ls, fs->nactvar+n+1, MAXVARS, "local variables");
- fs->actvar[fs->nactvar+n] = luaI_registerlocalvar(ls, name);
+ luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables");
+ fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name));
}
static void adjustlocalvars (LexState *ls, int nvars) {
FuncState *fs = ls->fs;
- fs->nactvar += nvars;
+ fs->nactvar = cast_byte(fs->nactvar + nvars);
for (; nvars; nvars--) {
getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc;
}
@@ -168,32 +180,26 @@ static void removevars (LexState *ls, int tolevel) {
}
-static void new_localvarstr (LexState *ls, const char *name, int n) {
- new_localvar(ls, luaS_new(ls->L, name), n);
-}
-
-
-static void create_local (LexState *ls, const char *name) {
- new_localvarstr(ls, name, 0);
- adjustlocalvars(ls, 1);
-}
-
-
static int indexupvalue (FuncState *fs, TString *name, expdesc *v) {
int i;
Proto *f = fs->f;
+ int oldsize = f->sizeupvalues;
for (i=0; i<f->nups; i++) {
- if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->info) {
- lua_assert(fs->f->upvalues[i] == name);
+ if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) {
+ lua_assert(f->upvalues[i] == name);
return i;
}
}
/* new one */
- luaX_checklimit(fs->ls, f->nups + 1, MAXUPVALUES, "upvalues");
- luaM_growvector(fs->L, fs->f->upvalues, f->nups, fs->f->sizeupvalues,
+ luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, "upvalues");
+ luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues,
TString *, MAX_INT, "");
- fs->f->upvalues[f->nups] = name;
- fs->upvalues[f->nups] = *v;
+ while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL;
+ f->upvalues[f->nups] = name;
+ luaC_objbarrier(fs->L, f, name);
+ lua_assert(v->k == VLOCAL || v->k == VUPVAL);
+ fs->upvalues[f->nups].k = cast_byte(v->k);
+ fs->upvalues[f->nups].info = cast_byte(v->u.s.info);
return f->nups++;
}
@@ -215,46 +221,46 @@ static void markupval (FuncState *fs, int level) {
}
-static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
- if (fs == NULL) /* no more levels? */
+static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
+ if (fs == NULL) { /* no more levels? */
init_exp(var, VGLOBAL, NO_REG); /* default is global variable */
+ return VGLOBAL;
+ }
else {
int v = searchvar(fs, n); /* look up at current level */
if (v >= 0) {
init_exp(var, VLOCAL, v);
if (!base)
markupval(fs, v); /* local will be used as an upval */
+ return VLOCAL;
}
else { /* not found at current level; try upper one */
- singlevaraux(fs->prev, n, var, 0);
- if (var->k == VGLOBAL) {
- if (base)
- var->info = luaK_stringK(fs, n); /* info points to global name */
- }
- else { /* LOCAL or UPVAL */
- var->info = indexupvalue(fs, n, var);
- var->k = VUPVAL; /* upvalue in this level */
- }
+ if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL)
+ return VGLOBAL;
+ var->u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */
+ var->k = VUPVAL; /* upvalue in this level */
+ return VUPVAL;
}
}
}
-static TString *singlevar (LexState *ls, expdesc *var, int base) {
+static void singlevar (LexState *ls, expdesc *var) {
TString *varname = str_checkname(ls);
- singlevaraux(ls->fs, varname, var, base);
- return varname;
+ FuncState *fs = ls->fs;
+ if (singlevaraux(fs, varname, var, 1) == VGLOBAL)
+ var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */
}
static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
FuncState *fs = ls->fs;
int extra = nvars - nexps;
- if (e->k == VCALL) {
+ if (hasmultret(e->k)) {
extra++; /* includes call itself */
- if (extra <= 0) extra = 0;
- else luaK_reserveregs(fs, extra-1);
- luaK_setcallreturns(fs, e, extra); /* call provides the difference */
+ if (extra < 0) extra = 0;
+ luaK_setreturns(fs, e, extra); /* last exp. provides the difference */
+ if (extra > 1) luaK_reserveregs(fs, extra-1);
}
else {
if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */
@@ -267,19 +273,16 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
}
-static void code_params (LexState *ls, int nparams, int dots) {
- FuncState *fs = ls->fs;
- adjustlocalvars(ls, nparams);
- luaX_checklimit(ls, fs->nactvar, MAXPARAMS, "parameters");
- fs->f->numparams = cast(lu_byte, fs->nactvar);
- fs->f->is_vararg = cast(lu_byte, dots);
- if (dots)
- create_local(ls, "arg");
- luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */
+static void enterlevel (LexState *ls) {
+ if (++ls->L->nCcalls > LUAI_MAXCCALLS)
+ luaX_lexerror(ls, "chunk has too many syntax levels", 0);
}
-static void enterblock (FuncState *fs, BlockCnt *bl, int isbreakable) {
+#define leavelevel(ls) ((ls)->L->nCcalls--)
+
+
+static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) {
bl->breaklist = NO_JUMP;
bl->isbreakable = isbreakable;
bl->nactvar = fs->nactvar;
@@ -296,6 +299,8 @@ static void leaveblock (FuncState *fs) {
removevars(fs->ls, bl->nactvar);
if (bl->upval)
luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
+ /* a block either controls scope or breaks (never both) */
+ lua_assert(!bl->isbreakable || !bl->upval);
lua_assert(bl->nactvar == fs->nactvar);
fs->freereg = fs->nactvar; /* free registers */
luaK_patchtohere(fs, bl->breaklist);
@@ -305,10 +310,13 @@ static void leaveblock (FuncState *fs) {
static void pushclosure (LexState *ls, FuncState *func, expdesc *v) {
FuncState *fs = ls->fs;
Proto *f = fs->f;
+ int oldsize = f->sizep;
int i;
luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *,
MAXARG_Bx, "constant table overflow");
+ while (oldsize < f->sizep) f->p[oldsize++] = NULL;
f->p[fs->np++] = func->f;
+ luaC_objbarrier(ls->L, f, func->f);
init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1));
for (i=0; i<func->f->nups; i++) {
OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL;
@@ -318,24 +326,30 @@ static void pushclosure (LexState *ls, FuncState *func, expdesc *v) {
static void open_func (LexState *ls, FuncState *fs) {
- Proto *f = luaF_newproto(ls->L);
+ lua_State *L = ls->L;
+ Proto *f = luaF_newproto(L);
fs->f = f;
fs->prev = ls->fs; /* linked list of funcstates */
fs->ls = ls;
- fs->L = ls->L;
+ fs->L = L;
ls->fs = fs;
fs->pc = 0;
- fs->lasttarget = 0;
+ fs->lasttarget = -1;
fs->jpc = NO_JUMP;
fs->freereg = 0;
fs->nk = 0;
- fs->h = luaH_new(ls->L, 0, 0);
fs->np = 0;
fs->nlocvars = 0;
fs->nactvar = 0;
fs->bl = NULL;
f->source = ls->source;
f->maxstacksize = 2; /* registers 0/1 are always valid */
+ fs->h = luaH_new(L, 0, 0);
+ /* anchor table of constants and prototype (to avoid being collected) */
+ sethvalue2s(L, L->top, fs->h);
+ incr_top(L);
+ setptvalue2s(L, L->top, f);
+ incr_top(L);
}
@@ -344,12 +358,12 @@ static void close_func (LexState *ls) {
FuncState *fs = ls->fs;
Proto *f = fs->f;
removevars(ls, 0);
- luaK_codeABC(fs, OP_RETURN, 0, 1, 0); /* final return */
+ luaK_ret(fs, 0, 0); /* final return */
luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);
f->sizecode = fs->pc;
luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);
f->sizelineinfo = fs->pc;
- luaM_reallocvector(L, f->k, f->sizek, fs->nk, TObject);
+ luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue);
f->sizek = fs->nk;
luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *);
f->sizep = fs->np;
@@ -360,23 +374,26 @@ static void close_func (LexState *ls) {
lua_assert(luaG_checkcode(f));
lua_assert(fs->bl == NULL);
ls->fs = fs->prev;
+ L->top -= 2; /* remove table and prototype from the stack */
+ /* last token read was anchored in defunct function; must reanchor it */
+ if (fs) anchor_token(ls);
}
-Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff) {
+Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
struct LexState lexstate;
struct FuncState funcstate;
lexstate.buff = buff;
- lexstate.nestlevel = 0;
- luaX_setinput(L, &lexstate, z, luaS_new(L, zname(z)));
+ luaX_setinput(L, &lexstate, z, luaS_new(L, name));
open_func(&lexstate, &funcstate);
- next(&lexstate); /* read first token */
+ funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */
+ luaX_next(&lexstate); /* read first token */
chunk(&lexstate);
- check_condition(&lexstate, (lexstate.t.token == TK_EOS), "<eof> expected");
+ check(&lexstate, TK_EOS);
close_func(&lexstate);
lua_assert(funcstate.prev == NULL);
lua_assert(funcstate.f->nups == 0);
- lua_assert(lexstate.nestlevel == 0);
+ lua_assert(lexstate.fs == NULL);
return funcstate.f;
}
@@ -387,23 +404,23 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff) {
/*============================================================*/
-static void luaY_field (LexState *ls, expdesc *v) {
+static void field (LexState *ls, expdesc *v) {
/* field -> ['.' | ':'] NAME */
FuncState *fs = ls->fs;
expdesc key;
luaK_exp2anyreg(fs, v);
- next(ls); /* skip the dot or colon */
+ luaX_next(ls); /* skip the dot or colon */
checkname(ls, &key);
luaK_indexed(fs, v, &key);
}
-static void luaY_index (LexState *ls, expdesc *v) {
+static void yindex (LexState *ls, expdesc *v) {
/* index -> '[' expr ']' */
- next(ls); /* skip the '[' */
+ luaX_next(ls); /* skip the '[' */
expr(ls, v);
luaK_exp2val(ls->fs, v);
- check(ls, ']');
+ checknext(ls, ']');
}
@@ -428,18 +445,18 @@ static void recfield (LexState *ls, struct ConsControl *cc) {
FuncState *fs = ls->fs;
int reg = ls->fs->freereg;
expdesc key, val;
+ int rkkey;
if (ls->t.token == TK_NAME) {
- luaX_checklimit(ls, cc->nh, MAX_INT, "items in a constructor");
- cc->nh++;
+ luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor");
checkname(ls, &key);
}
else /* ls->t.token == '[' */
- luaY_index(ls, &key);
- check(ls, '=');
- luaK_exp2RK(fs, &key);
+ yindex(ls, &key);
+ cc->nh++;
+ checknext(ls, '=');
+ rkkey = luaK_exp2RK(fs, &key);
expr(ls, &val);
- luaK_codeABC(fs, OP_SETTABLE, cc->t->info, luaK_exp2RK(fs, &key),
- luaK_exp2RK(fs, &val));
+ luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val));
fs->freereg = reg; /* free registers */
}
@@ -449,31 +466,30 @@ static void closelistfield (FuncState *fs, struct ConsControl *cc) {
luaK_exp2nextreg(fs, &cc->v);
cc->v.k = VVOID;
if (cc->tostore == LFIELDS_PER_FLUSH) {
- luaK_codeABx(fs, OP_SETLIST, cc->t->info, cc->na-1); /* flush */
+ luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); /* flush */
cc->tostore = 0; /* no more items pending */
- fs->freereg = cc->t->info + 1; /* free registers */
}
}
static void lastlistfield (FuncState *fs, struct ConsControl *cc) {
if (cc->tostore == 0) return;
- if (cc->v.k == VCALL) {
- luaK_setcallreturns(fs, &cc->v, LUA_MULTRET);
- luaK_codeABx(fs, OP_SETLISTO, cc->t->info, cc->na-1);
+ if (hasmultret(cc->v.k)) {
+ luaK_setmultret(fs, &cc->v);
+ luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET);
+ cc->na--; /* do not count last expression (unknown number of elements) */
}
else {
if (cc->v.k != VVOID)
luaK_exp2nextreg(fs, &cc->v);
- luaK_codeABx(fs, OP_SETLIST, cc->t->info, cc->na-1);
+ luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore);
}
- fs->freereg = cc->t->info + 1; /* free registers */
}
static void listfield (LexState *ls, struct ConsControl *cc) {
expr(ls, &cc->v);
- luaX_checklimit(ls, cc->na, MAXARG_Bx, "items in a constructor");
+ luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor");
cc->na++;
cc->tostore++;
}
@@ -490,15 +506,14 @@ static void constructor (LexState *ls, expdesc *t) {
init_exp(t, VRELOCABLE, pc);
init_exp(&cc.v, VVOID, 0); /* no value (yet) */
luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */
- check(ls, '{');
+ checknext(ls, '{');
do {
lua_assert(cc.v.k == VVOID || cc.tostore > 0);
- testnext(ls, ';'); /* compatibility only */
if (ls->t.token == '}') break;
closelistfield(fs, &cc);
switch(ls->t.token) {
case TK_NAME: { /* may be listfields or recfields */
- lookahead(ls);
+ luaX_lookahead(ls);
if (ls->lookahead.token != '=') /* expression? */
listfield(ls, &cc);
else
@@ -518,7 +533,7 @@ static void constructor (LexState *ls, expdesc *t) {
check_match(ls, '}', '{', line);
lastlistfield(fs, &cc);
SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */
- SETARG_C(fs->f->code[pc], luaO_log2(cc.nh)+1); /* set initial table size */
+ SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */
}
/* }====================================================================== */
@@ -527,18 +542,34 @@ static void constructor (LexState *ls, expdesc *t) {
static void parlist (LexState *ls) {
/* parlist -> [ param { `,' param } ] */
+ FuncState *fs = ls->fs;
+ Proto *f = fs->f;
int nparams = 0;
- int dots = 0;
+ f->is_vararg = 0;
if (ls->t.token != ')') { /* is `parlist' not empty? */
do {
switch (ls->t.token) {
- case TK_DOTS: dots = 1; next(ls); break;
- case TK_NAME: new_localvar(ls, str_checkname(ls), nparams++); break;
- default: luaX_syntaxerror(ls, "<name> or `...' expected");
+ case TK_NAME: { /* param -> NAME */
+ new_localvar(ls, str_checkname(ls), nparams++);
+ break;
+ }
+ case TK_DOTS: { /* param -> `...' */
+ luaX_next(ls);
+#if defined(LUA_COMPAT_VARARG)
+ /* use `arg' as default name */
+ new_localvarliteral(ls, "arg", nparams++);
+ f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG;
+#endif
+ f->is_vararg |= VARARG_ISVARARG;
+ break;
+ }
+ default: luaX_syntaxerror(ls, "<name> or " LUA_QL("...") " expected");
}
- } while (!dots && testnext(ls, ','));
+ } while (!f->is_vararg && testnext(ls, ','));
}
- code_params(ls, nparams, dots);
+ adjustlocalvars(ls, nparams);
+ f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG));
+ luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */
}
@@ -546,13 +577,16 @@ static void body (LexState *ls, expdesc *e, int needself, int line) {
/* body -> `(' parlist `)' chunk END */
FuncState new_fs;
open_func(ls, &new_fs);
- new_fs.f->lineDefined = line;
- check(ls, '(');
- if (needself)
- create_local(ls, "self");
+ new_fs.f->linedefined = line;
+ checknext(ls, '(');
+ if (needself) {
+ new_localvarliteral(ls, "self", 0);
+ adjustlocalvars(ls, 1);
+ }
parlist(ls);
- check(ls, ')');
+ checknext(ls, ')');
chunk(ls);
+ new_fs.f->lastlinedefined = ls->linenumber;
check_match(ls, TK_END, TK_FUNCTION, line);
close_func(ls);
pushclosure(ls, &new_fs, e);
@@ -581,12 +615,12 @@ static void funcargs (LexState *ls, expdesc *f) {
case '(': { /* funcargs -> `(' [ explist1 ] `)' */
if (line != ls->lastline)
luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)");
- next(ls);
+ luaX_next(ls);
if (ls->t.token == ')') /* arg list is empty? */
args.k = VVOID;
else {
explist1(ls, &args);
- luaK_setcallreturns(fs, &args, LUA_MULTRET);
+ luaK_setmultret(fs, &args);
}
check_match(ls, ')', '(', line);
break;
@@ -597,7 +631,7 @@ static void funcargs (LexState *ls, expdesc *f) {
}
case TK_STRING: { /* funcargs -> STRING */
codestring(ls, &args, ls->t.seminfo.ts);
- next(ls); /* must use `seminfo' before `next' */
+ luaX_next(ls); /* must use `seminfo' before `next' */
break;
}
default: {
@@ -606,8 +640,8 @@ static void funcargs (LexState *ls, expdesc *f) {
}
}
lua_assert(f->k == VNONRELOC);
- base = f->info; /* base register for call */
- if (args.k == VCALL)
+ base = f->u.s.info; /* base register for call */
+ if (hasmultret(args.k))
nparams = LUA_MULTRET; /* open call */
else {
if (args.k != VVOID)
@@ -635,28 +669,16 @@ static void prefixexp (LexState *ls, expdesc *v) {
switch (ls->t.token) {
case '(': {
int line = ls->linenumber;
- next(ls);
+ luaX_next(ls);
expr(ls, v);
check_match(ls, ')', '(', line);
luaK_dischargevars(ls->fs, v);
return;
}
case TK_NAME: {
- singlevar(ls, v, 1);
- return;
- }
-#ifdef LUA_COMPATUPSYNTAX
- case '%': { /* for compatibility only */
- TString *varname;
- int line = ls->linenumber;
- next(ls); /* skip `%' */
- varname = singlevar(ls, v, 1);
- if (v->k != VUPVAL)
- luaX_errorline(ls, "global upvalues are obsolete",
- getstr(varname), line);
+ singlevar(ls, v);
return;
}
-#endif
default: {
luaX_syntaxerror(ls, "unexpected symbol");
return;
@@ -673,19 +695,19 @@ static void primaryexp (LexState *ls, expdesc *v) {
for (;;) {
switch (ls->t.token) {
case '.': { /* field */
- luaY_field(ls, v);
+ field(ls, v);
break;
}
case '[': { /* `[' exp1 `]' */
expdesc key;
luaK_exp2anyreg(fs, v);
- luaY_index(ls, &key);
+ yindex(ls, &key);
luaK_indexed(fs, v, &key);
break;
}
case ':': { /* `:' NAME funcargs */
expdesc key;
- next(ls);
+ luaX_next(ls);
checkname(ls, &key);
luaK_self(fs, v, &key);
funcargs(ls, v);
@@ -703,48 +725,53 @@ static void primaryexp (LexState *ls, expdesc *v) {
static void simpleexp (LexState *ls, expdesc *v) {
- /* simpleexp -> NUMBER | STRING | NIL | constructor | FUNCTION body
- | primaryexp */
+ /* simpleexp -> NUMBER | STRING | NIL | true | false | ... |
+ constructor | FUNCTION body | primaryexp */
switch (ls->t.token) {
case TK_NUMBER: {
- init_exp(v, VK, luaK_numberK(ls->fs, ls->t.seminfo.r));
- next(ls); /* must use `seminfo' before `next' */
+ init_exp(v, VKNUM, 0);
+ v->u.nval = ls->t.seminfo.r;
break;
}
case TK_STRING: {
codestring(ls, v, ls->t.seminfo.ts);
- next(ls); /* must use `seminfo' before `next' */
break;
}
case TK_NIL: {
init_exp(v, VNIL, 0);
- next(ls);
break;
}
case TK_TRUE: {
init_exp(v, VTRUE, 0);
- next(ls);
break;
}
case TK_FALSE: {
init_exp(v, VFALSE, 0);
- next(ls);
+ break;
+ }
+ case TK_DOTS: { /* vararg */
+ FuncState *fs = ls->fs;
+ check_condition(ls, fs->f->is_vararg,
+ "cannot use " LUA_QL("...") " outside a vararg function");
+ fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */
+ init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0));
break;
}
case '{': { /* constructor */
constructor(ls, v);
- break;
+ return;
}
case TK_FUNCTION: {
- next(ls);
+ luaX_next(ls);
body(ls, v, 0, ls->linenumber);
- break;
+ return;
}
default: {
primaryexp(ls, v);
- break;
+ return;
}
}
+ luaX_next(ls);
}
@@ -752,6 +779,7 @@ static UnOpr getunopr (int op) {
switch (op) {
case TK_NOT: return OPR_NOT;
case '-': return OPR_MINUS;
+ case '#': return OPR_LEN;
default: return OPR_NOUNOPR;
}
}
@@ -761,8 +789,9 @@ static BinOpr getbinopr (int op) {
switch (op) {
case '+': return OPR_ADD;
case '-': return OPR_SUB;
- case '*': return OPR_MULT;
+ case '*': return OPR_MUL;
case '/': return OPR_DIV;
+ case '%': return OPR_MOD;
case '^': return OPR_POW;
case TK_CONCAT: return OPR_CONCAT;
case TK_NE: return OPR_NE;
@@ -782,9 +811,9 @@ static const struct {
lu_byte left; /* left priority for each binary operator */
lu_byte right; /* right priority */
} priority[] = { /* ORDER OPR */
- {6, 6}, {6, 6}, {7, 7}, {7, 7}, /* arithmetic */
+ {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */
{10, 9}, {5, 4}, /* power and concat (right associative) */
- {3, 3}, {3, 3}, /* equality */
+ {3, 3}, {3, 3}, /* equality and inequality */
{3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */
{2, 2}, {1, 1} /* logical (and/or) */
};
@@ -793,29 +822,29 @@ static const struct {
/*
-** subexpr -> (simplexep | unop subexpr) { binop subexpr }
+** subexpr -> (simpleexp | unop subexpr) { binop subexpr }
** where `binop' is any binary operator with a priority higher than `limit'
*/
-static BinOpr subexpr (LexState *ls, expdesc *v, int limit) {
+static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) {
BinOpr op;
UnOpr uop;
enterlevel(ls);
uop = getunopr(ls->t.token);
if (uop != OPR_NOUNOPR) {
- next(ls);
+ luaX_next(ls);
subexpr(ls, v, UNARY_PRIORITY);
luaK_prefix(ls->fs, uop, v);
}
else simpleexp(ls, v);
/* expand while operators have priorities higher than `limit' */
op = getbinopr(ls->t.token);
- while (op != OPR_NOBINOPR && cast(int, priority[op].left) > limit) {
+ while (op != OPR_NOBINOPR && priority[op].left > limit) {
expdesc v2;
BinOpr nextop;
- next(ls);
+ luaX_next(ls);
luaK_infix(ls->fs, op, v);
/* read sub-expression with higher priority */
- nextop = subexpr(ls, &v2, cast(int, priority[op].right));
+ nextop = subexpr(ls, &v2, priority[op].right);
luaK_posfix(ls->fs, op, v, &v2);
op = nextop;
}
@@ -825,7 +854,7 @@ static BinOpr subexpr (LexState *ls, expdesc *v, int limit) {
static void expr (LexState *ls, expdesc *v) {
- subexpr(ls, v, -1);
+ subexpr(ls, v, 0);
}
/* }==================================================================== */
@@ -882,18 +911,18 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
int conflict = 0;
for (; lh; lh = lh->prev) {
if (lh->v.k == VINDEXED) {
- if (lh->v.info == v->info) { /* conflict? */
+ if (lh->v.u.s.info == v->u.s.info) { /* conflict? */
conflict = 1;
- lh->v.info = extra; /* previous assignment will use safe copy */
+ lh->v.u.s.info = extra; /* previous assignment will use safe copy */
}
- if (lh->v.aux == v->info) { /* conflict? */
+ if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */
conflict = 1;
- lh->v.aux = extra; /* previous assignment will use safe copy */
+ lh->v.u.s.aux = extra; /* previous assignment will use safe copy */
}
}
}
if (conflict) {
- luaK_codeABC(fs, OP_MOVE, fs->freereg, v->info, 0); /* make copy */
+ luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */
luaK_reserveregs(fs, 1);
}
}
@@ -913,7 +942,7 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
}
else { /* assignment -> `=' explist1 */
int nexps;
- check(ls, '=');
+ checknext(ls, '=');
nexps = explist1(ls, &e);
if (nexps != nvars) {
adjust_assign(ls, nvars, nexps, &e);
@@ -921,7 +950,7 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
ls->fs->freereg -= nexps - nvars; /* remove extra values */
}
else {
- luaK_setcallreturns(ls->fs, &e, 1); /* close last expression */
+ luaK_setoneret(ls->fs, &e); /* close last expression */
luaK_storevar(ls->fs, &lh->v, &e);
return; /* avoid default */
}
@@ -931,88 +960,74 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
}
-static void cond (LexState *ls, expdesc *v) {
+static int cond (LexState *ls) {
/* cond -> exp */
- expr(ls, v); /* read condition */
- if (v->k == VNIL) v->k = VFALSE; /* `falses' are all equal here */
- luaK_goiftrue(ls->fs, v);
- luaK_patchtohere(ls->fs, v->t);
+ expdesc v;
+ expr(ls, &v); /* read condition */
+ if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */
+ luaK_goiftrue(ls->fs, &v);
+ return v.f;
}
-/*
-** The while statement optimizes its code by coding the condition
-** after its body (and thus avoiding one jump in the loop).
-*/
-
-/*
-** maximum size of expressions for optimizing `while' code
-*/
-#ifndef MAXEXPWHILE
-#define MAXEXPWHILE 100
-#endif
+static void breakstat (LexState *ls) {
+ FuncState *fs = ls->fs;
+ BlockCnt *bl = fs->bl;
+ int upval = 0;
+ while (bl && !bl->isbreakable) {
+ upval |= bl->upval;
+ bl = bl->previous;
+ }
+ if (!bl)
+ luaX_syntaxerror(ls, "no loop to break");
+ if (upval)
+ luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
+ luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
+}
-/*
-** the call `luaK_goiffalse' may grow the size of an expression by
-** at most this:
-*/
-#define EXTRAEXP 5
static void whilestat (LexState *ls, int line) {
/* whilestat -> WHILE cond DO block END */
- Instruction codeexp[MAXEXPWHILE + EXTRAEXP];
- int lineexp;
- int i;
- int sizeexp;
FuncState *fs = ls->fs;
- int whileinit, blockinit, expinit;
- expdesc v;
+ int whileinit;
+ int condexit;
BlockCnt bl;
- next(ls); /* skip WHILE */
- whileinit = luaK_jump(fs); /* jump to condition (which will be moved) */
- expinit = luaK_getlabel(fs);
- expr(ls, &v); /* parse condition */
- if (v.k == VK) v.k = VTRUE; /* `trues' are all equal here */
- lineexp = ls->linenumber;
- luaK_goiffalse(fs, &v);
- luaK_concat(fs, &v.f, fs->jpc);
- fs->jpc = NO_JUMP;
- sizeexp = fs->pc - expinit; /* size of expression code */
- if (sizeexp > MAXEXPWHILE)
- luaX_syntaxerror(ls, "`while' condition too complex");
- for (i = 0; i < sizeexp; i++) /* save `exp' code */
- codeexp[i] = fs->f->code[expinit + i];
- fs->pc = expinit; /* remove `exp' code */
+ luaX_next(ls); /* skip WHILE */
+ whileinit = luaK_getlabel(fs);
+ condexit = cond(ls);
enterblock(fs, &bl, 1);
- check(ls, TK_DO);
- blockinit = luaK_getlabel(fs);
+ checknext(ls, TK_DO);
block(ls);
- luaK_patchtohere(fs, whileinit); /* initial jump jumps to here */
- /* move `exp' back to code */
- if (v.t != NO_JUMP) v.t += fs->pc - expinit;
- if (v.f != NO_JUMP) v.f += fs->pc - expinit;
- for (i=0; i<sizeexp; i++)
- luaK_code(fs, codeexp[i], lineexp);
+ luaK_patchlist(fs, luaK_jump(fs), whileinit);
check_match(ls, TK_END, TK_WHILE, line);
leaveblock(fs);
- luaK_patchlist(fs, v.t, blockinit); /* true conditions go back to loop */
- luaK_patchtohere(fs, v.f); /* false conditions finish the loop */
+ luaK_patchtohere(fs, condexit); /* false conditions finish the loop */
}
static void repeatstat (LexState *ls, int line) {
/* repeatstat -> REPEAT block UNTIL cond */
+ int condexit;
FuncState *fs = ls->fs;
int repeat_init = luaK_getlabel(fs);
- expdesc v;
- BlockCnt bl;
- enterblock(fs, &bl, 1);
- next(ls);
- block(ls);
+ BlockCnt bl1, bl2;
+ enterblock(fs, &bl1, 1); /* loop block */
+ enterblock(fs, &bl2, 0); /* scope block */
+ luaX_next(ls); /* skip REPEAT */
+ chunk(ls);
check_match(ls, TK_UNTIL, TK_REPEAT, line);
- cond(ls, &v);
- luaK_patchlist(fs, v.f, repeat_init);
- leaveblock(fs);
+ condexit = cond(ls); /* read condition (inside scope block) */
+ if (!bl2.upval) { /* no upvalues? */
+ leaveblock(fs); /* finish scope */
+ luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */
+ }
+ else { /* complete semantics when there are upvalues */
+ breakstat(ls); /* if condition then break */
+ luaK_patchtohere(ls->fs, condexit); /* else... */
+ leaveblock(fs); /* finish scope... */
+ luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */
+ }
+ leaveblock(fs); /* finish loop */
}
@@ -1027,33 +1042,37 @@ static int exp1 (LexState *ls) {
static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
+ /* forbody -> DO block */
BlockCnt bl;
FuncState *fs = ls->fs;
int prep, endfor;
- adjustlocalvars(ls, nvars); /* scope for all variables */
- check(ls, TK_DO);
- enterblock(fs, &bl, 1); /* loop block */
- prep = luaK_getlabel(fs);
+ adjustlocalvars(ls, 3); /* control variables */
+ checknext(ls, TK_DO);
+ prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs);
+ enterblock(fs, &bl, 0); /* scope for declared variables */
+ adjustlocalvars(ls, nvars);
+ luaK_reserveregs(fs, nvars);
block(ls);
- luaK_patchtohere(fs, prep-1);
+ leaveblock(fs); /* end of scope for declared variables */
+ luaK_patchtohere(fs, prep);
endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) :
- luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars - 3);
+ luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars);
luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */
- luaK_patchlist(fs, (isnum) ? endfor : luaK_jump(fs), prep);
- leaveblock(fs);
+ luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1);
}
static void fornum (LexState *ls, TString *varname, int line) {
- /* fornum -> NAME = exp1,exp1[,exp1] DO body */
+ /* fornum -> NAME = exp1,exp1[,exp1] forbody */
FuncState *fs = ls->fs;
int base = fs->freereg;
- new_localvar(ls, varname, 0);
- new_localvarstr(ls, "(for limit)", 1);
- new_localvarstr(ls, "(for step)", 2);
- check(ls, '=');
+ new_localvarliteral(ls, "(for index)", 0);
+ new_localvarliteral(ls, "(for limit)", 1);
+ new_localvarliteral(ls, "(for step)", 2);
+ new_localvar(ls, varname, 3);
+ checknext(ls, '=');
exp1(ls); /* initial value */
- check(ls, ',');
+ checknext(ls, ',');
exp1(ls); /* limit */
if (testnext(ls, ','))
exp1(ls); /* optional step */
@@ -1061,79 +1080,81 @@ static void fornum (LexState *ls, TString *varname, int line) {
luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));
luaK_reserveregs(fs, 1);
}
- luaK_codeABC(fs, OP_SUB, fs->freereg - 3, fs->freereg - 3, fs->freereg - 1);
- luaK_jump(fs);
- forbody(ls, base, line, 3, 1);
+ forbody(ls, base, line, 1, 1);
}
static void forlist (LexState *ls, TString *indexname) {
- /* forlist -> NAME {,NAME} IN explist1 DO body */
+ /* forlist -> NAME {,NAME} IN explist1 forbody */
FuncState *fs = ls->fs;
expdesc e;
int nvars = 0;
int line;
int base = fs->freereg;
- new_localvarstr(ls, "(for generator)", nvars++);
- new_localvarstr(ls, "(for state)", nvars++);
+ /* create control variables */
+ new_localvarliteral(ls, "(for generator)", nvars++);
+ new_localvarliteral(ls, "(for state)", nvars++);
+ new_localvarliteral(ls, "(for control)", nvars++);
+ /* create declared variables */
new_localvar(ls, indexname, nvars++);
while (testnext(ls, ','))
new_localvar(ls, str_checkname(ls), nvars++);
- check(ls, TK_IN);
+ checknext(ls, TK_IN);
line = ls->linenumber;
- adjust_assign(ls, nvars, explist1(ls, &e), &e);
+ adjust_assign(ls, 3, explist1(ls, &e), &e);
luaK_checkstack(fs, 3); /* extra space to call generator */
- luaK_codeAsBx(fs, OP_TFORPREP, base, NO_JUMP);
- forbody(ls, base, line, nvars, 0);
+ forbody(ls, base, line, nvars - 3, 0);
}
static void forstat (LexState *ls, int line) {
- /* forstat -> fornum | forlist */
+ /* forstat -> FOR (fornum | forlist) END */
FuncState *fs = ls->fs;
TString *varname;
BlockCnt bl;
- enterblock(fs, &bl, 0); /* block to control variable scope */
- next(ls); /* skip `for' */
+ enterblock(fs, &bl, 1); /* scope for loop and control variables */
+ luaX_next(ls); /* skip `for' */
varname = str_checkname(ls); /* first variable name */
switch (ls->t.token) {
case '=': fornum(ls, varname, line); break;
case ',': case TK_IN: forlist(ls, varname); break;
- default: luaX_syntaxerror(ls, "`=' or `in' expected");
+ default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected");
}
check_match(ls, TK_END, TK_FOR, line);
- leaveblock(fs);
+ leaveblock(fs); /* loop scope (`break' jumps to this point) */
}
-static void test_then_block (LexState *ls, expdesc *v) {
+static int test_then_block (LexState *ls) {
/* test_then_block -> [IF | ELSEIF] cond THEN block */
- next(ls); /* skip IF or ELSEIF */
- cond(ls, v);
- check(ls, TK_THEN);
+ int condexit;
+ luaX_next(ls); /* skip IF or ELSEIF */
+ condexit = cond(ls);
+ checknext(ls, TK_THEN);
block(ls); /* `then' part */
+ return condexit;
}
static void ifstat (LexState *ls, int line) {
/* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */
FuncState *fs = ls->fs;
- expdesc v;
+ int flist;
int escapelist = NO_JUMP;
- test_then_block(ls, &v); /* IF cond THEN block */
+ flist = test_then_block(ls); /* IF cond THEN block */
while (ls->t.token == TK_ELSEIF) {
luaK_concat(fs, &escapelist, luaK_jump(fs));
- luaK_patchtohere(fs, v.f);
- test_then_block(ls, &v); /* ELSEIF cond THEN block */
+ luaK_patchtohere(fs, flist);
+ flist = test_then_block(ls); /* ELSEIF cond THEN block */
}
if (ls->t.token == TK_ELSE) {
luaK_concat(fs, &escapelist, luaK_jump(fs));
- luaK_patchtohere(fs, v.f);
- next(ls); /* skip ELSE (after patch, for correct line info) */
+ luaK_patchtohere(fs, flist);
+ luaX_next(ls); /* skip ELSE (after patch, for correct line info) */
block(ls); /* `else' part */
}
else
- luaK_concat(fs, &escapelist, v.f);
+ luaK_concat(fs, &escapelist, flist);
luaK_patchtohere(fs, escapelist);
check_match(ls, TK_END, TK_IF, line);
}
@@ -1175,12 +1196,12 @@ static void localstat (LexState *ls) {
static int funcname (LexState *ls, expdesc *v) {
/* funcname -> NAME {field} [`:' NAME] */
int needself = 0;
- singlevar(ls, v, 1);
+ singlevar(ls, v);
while (ls->t.token == '.')
- luaY_field(ls, v);
+ field(ls, v);
if (ls->t.token == ':') {
needself = 1;
- luaY_field(ls, v);
+ field(ls, v);
}
return needself;
}
@@ -1190,7 +1211,7 @@ static void funcstat (LexState *ls, int line) {
/* funcstat -> FUNCTION funcname body */
int needself;
expdesc v, b;
- next(ls); /* skip FUNCTION */
+ luaX_next(ls); /* skip FUNCTION */
needself = funcname(ls, &v);
body(ls, &b, needself, line);
luaK_storevar(ls->fs, &v, &b);
@@ -1203,9 +1224,8 @@ static void exprstat (LexState *ls) {
FuncState *fs = ls->fs;
struct LHS_assign v;
primaryexp(ls, &v.v);
- if (v.v.k == VCALL) { /* stat -> func */
- luaK_setcallreturns(fs, &v.v, 0); /* call statement uses no results */
- }
+ if (v.v.k == VCALL) /* stat -> func */
+ SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */
else { /* stat -> assignment */
v.prev = NULL;
assignment(ls, &v, 1);
@@ -1218,14 +1238,14 @@ static void retstat (LexState *ls) {
FuncState *fs = ls->fs;
expdesc e;
int first, nret; /* registers with returned values */
- next(ls); /* skip RETURN */
+ luaX_next(ls); /* skip RETURN */
if (block_follow(ls->t.token) || ls->t.token == ';')
first = nret = 0; /* return no values */
else {
nret = explist1(ls, &e); /* optional return values */
- if (e.k == VCALL) {
- luaK_setcallreturns(fs, &e, LUA_MULTRET);
- if (nret == 1) { /* tail call? */
+ if (hasmultret(e.k)) {
+ luaK_setmultret(fs, &e);
+ if (e.k == VCALL && nret == 1) { /* tail call? */
SET_OPCODE(getcode(fs,&e), OP_TAILCALL);
lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar);
}
@@ -1242,25 +1262,7 @@ static void retstat (LexState *ls) {
}
}
}
- luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);
-}
-
-
-static void breakstat (LexState *ls) {
- /* stat -> BREAK [NAME] */
- FuncState *fs = ls->fs;
- BlockCnt *bl = fs->bl;
- int upval = 0;
- next(ls); /* skip BREAK */
- while (bl && !bl->isbreakable) {
- upval |= bl->upval;
- bl = bl->previous;
- }
- if (!bl)
- luaX_syntaxerror(ls, "no loop to break");
- if (upval)
- luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
- luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
+ luaK_ret(fs, first, nret);
}
@@ -1276,7 +1278,7 @@ static int statement (LexState *ls) {
return 0;
}
case TK_DO: { /* stat -> DO block END */
- next(ls); /* skip DO */
+ luaX_next(ls); /* skip DO */
block(ls);
check_match(ls, TK_END, TK_DO, line);
return 0;
@@ -1294,7 +1296,7 @@ static int statement (LexState *ls) {
return 0;
}
case TK_LOCAL: { /* stat -> localstat */
- next(ls); /* skip LOCAL */
+ luaX_next(ls); /* skip LOCAL */
if (testnext(ls, TK_FUNCTION)) /* local function? */
localfunc(ls);
else
@@ -1306,6 +1308,7 @@ static int statement (LexState *ls) {
return 1; /* must be last statement */
}
case TK_BREAK: { /* stat -> breakstat */
+ luaX_next(ls); /* skip BREAK */
breakstat(ls);
return 1; /* must be last statement */
}
@@ -1324,7 +1327,8 @@ static void chunk (LexState *ls) {
while (!islast && !block_follow(ls->t.token)) {
islast = statement(ls);
testnext(ls, ';');
- lua_assert(ls->fs->freereg >= ls->fs->nactvar);
+ lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg &&
+ ls->fs->freereg >= ls->fs->nactvar);
ls->fs->freereg = ls->fs->nactvar; /* free registers */
}
leavelevel(ls);
diff --git a/lib/lua/src/lstate.c b/lib/lua/src/lstate.c
index a2618a5..8d5f3a6 100644
--- a/lib/lua/src/lstate.c
+++ b/lib/lua/src/lstate.c
@@ -1,13 +1,14 @@
/*
-** $Id: lstate.c,v 1.6 2006-02-09 16:59:55 pixel Exp $
+** $Id: lstate.c,v 1.7 2007-07-27 10:05:54 pixel Exp $
** Global State
** See Copyright Notice in lua.h
*/
-#include <stdlib.h>
+#include <stddef.h>
#define lstate_c
+#define LUA_CORE
#include "lua.h"
@@ -23,63 +24,43 @@
#include "ltm.h"
-/*
-** macro to allow the inclusion of user information in Lua state
-*/
-#ifndef LUA_USERSTATE
-#define EXTRASPACE 0
-#else
-union UEXTRASPACE {L_Umaxalign a; LUA_USERSTATE b;};
-#define EXTRASPACE (sizeof(union UEXTRASPACE))
-#endif
-
+#define state_size(x) (sizeof(x) + LUAI_EXTRASPACE)
+#define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE)
+#define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE))
/*
-** you can change this function through the official API:
-** call `lua_setpanicf'
+** Main thread combines a thread state and the global state
*/
-static int default_panic (lua_State *L) {
- UNUSED(L);
- return 0;
-}
-
-
-static lua_State *mallocstate (lua_State *L) {
- lu_byte *block = (lu_byte *)luaM_malloc(L, sizeof(lua_State) + EXTRASPACE);
- if (block == NULL) return NULL;
- else {
- block += EXTRASPACE;
- return cast(lua_State *, block);
- }
-}
-
-
-static void freestate (lua_State *L, lua_State *L1) {
- luaM_free(L, cast(lu_byte *, L1) - EXTRASPACE,
- sizeof(lua_State) + EXTRASPACE);
-}
+typedef struct LG {
+ lua_State l;
+ global_State g;
+} LG;
+
static void stack_init (lua_State *L1, lua_State *L) {
- L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TObject);
+ /* initialize CallInfo array */
+ L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);
+ L1->ci = L1->base_ci;
+ L1->size_ci = BASIC_CI_SIZE;
+ L1->end_ci = L1->base_ci + L1->size_ci - 1;
+ /* initialize stack array */
+ L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue);
L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
L1->top = L1->stack;
L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1;
- L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);
- L1->ci = L1->base_ci;
- L1->ci->state = CI_C; /* not a Lua function */
+ /* initialize first ci */
+ L1->ci->func = L1->top;
setnilvalue(L1->top++); /* `function' entry for this `ci' */
L1->base = L1->ci->base = L1->top;
L1->ci->top = L1->top + LUA_MINSTACK;
- L1->size_ci = BASIC_CI_SIZE;
- L1->end_ci = L1->base_ci + L1->size_ci;
}
static void freestack (lua_State *L, lua_State *L1) {
luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo);
- luaM_freearray(L, L1->stack, L1->stacksize, TObject);
+ luaM_freearray(L, L1->stack, L1->stacksize, TValue);
}
@@ -87,119 +68,132 @@ static void freestack (lua_State *L, lua_State *L1) {
** open parts that may cause memory-allocation errors
*/
static void f_luaopen (lua_State *L, void *ud) {
- /* create a new global state */
- global_State *g = luaM_new(NULL, global_State);
+ global_State *g = G(L);
UNUSED(ud);
- if (g == NULL) luaD_throw(L, LUA_ERRMEM);
- L->l_G = g;
- g->mainthread = L;
- g->GCthreshold = 0; /* mark it as unfinished state */
- g->strt.size = 0;
- g->strt.nuse = 0;
- g->strt.hash = NULL;
- setnilvalue(defaultmeta(L));
- setnilvalue(registry(L));
- luaZ_initbuffer(L, &g->buff);
- g->panic = default_panic;
- g->rootgc = NULL;
- g->rootudata = NULL;
- g->tmudata = NULL;
- setnilvalue(gkey(g->dummynode));
- setnilvalue(gval(g->dummynode));
- g->dummynode->next = NULL;
- g->nblocks = sizeof(lua_State) + sizeof(global_State);
stack_init(L, L); /* init stack */
- /* create default meta table with a dummy table, and then close the loop */
- defaultmeta(L)->tt = LUA_TTABLE;
- sethvalue(defaultmeta(L), luaH_new(L, 0, 0));
- hvalue(defaultmeta(L))->metatable = hvalue(defaultmeta(L));
- sethvalue(gt(L), luaH_new(L, 0, 4)); /* table of globals */
- sethvalue(registry(L), luaH_new(L, 4, 4)); /* registry */
+ sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */
+ sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */
luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */
luaT_init(L);
luaX_init(L);
luaS_fix(luaS_newliteral(L, MEMERRMSG));
- g->GCthreshold = 4*G(L)->nblocks;
+ g->GCthreshold = 4*g->totalbytes;
}
-static void preinit_state (lua_State *L) {
+static void preinit_state (lua_State *L, global_State *g) {
+ G(L) = g;
L->stack = NULL;
L->stacksize = 0;
L->errorJmp = NULL;
L->hook = NULL;
- L->hookmask = L->hookinit = 0;
+ L->hookmask = 0;
L->basehookcount = 0;
L->allowhook = 1;
resethookcount(L);
L->openupval = NULL;
L->size_ci = 0;
L->nCcalls = 0;
+ L->status = 0;
L->base_ci = L->ci = NULL;
+ L->savedpc = NULL;
L->errfunc = 0;
L->callwrap = 0;
L->createhook = 0;
L->destroyhook = 0;
+ L->do_break = 0;
setnilvalue(gt(L));
}
static void close_state (lua_State *L) {
+ global_State *g = G(L);
luaF_close(L, L->stack); /* close all upvalues for this thread */
- if (G(L)) { /* close global state */
- luaC_sweep(L, 1); /* collect all elements */
- lua_assert(G(L)->rootgc == NULL);
- lua_assert(G(L)->rootudata == NULL);
- luaS_freeall(L);
- luaZ_freebuffer(L, &G(L)->buff);
- }
+ luaC_freeall(L); /* collect all objects */
+ lua_assert(g->rootgc == obj2gco(L));
+ lua_assert(g->strt.nuse == 0);
+ luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);
+ luaZ_freebuffer(L, &g->buff);
freestack(L, L);
- if (G(L)) {
- lua_assert(G(L)->nblocks == sizeof(lua_State) + sizeof(global_State));
- luaM_freelem(NULL, G(L));
- }
- freestate(NULL, L);
+ lua_assert(g->totalbytes == sizeof(LG));
+ (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0);
}
lua_State *luaE_newthread (lua_State *L) {
- lua_State *L1 = mallocstate(L);
- luaC_link(L, valtogco(L1), LUA_TTHREAD);
- preinit_state(L1);
- L1->l_G = L->l_G;
+ lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State)));
+ luaC_link(L, obj2gco(L1), LUA_TTHREAD);
+ preinit_state(L1, G(L));
stack_init(L1, L); /* init stack */
- setobj2n(gt(L1), gt(L)); /* share table of globals */
+ setobj2n(L, gt(L1), gt(L)); /* share table of globals */
+ L1->hookmask = L->hookmask;
+ L1->basehookcount = L->basehookcount;
+ L1->hook = L->hook;
+ resethookcount(L1);
+ lua_assert(iswhite(obj2gco(L1)));
if (L->createhook)
- L->createhook(L, L1);
+ L->createhook(L, L1);
return L1;
}
void luaE_freethread (lua_State *L, lua_State *L1) {
if (L->destroyhook)
- L->destroyhook(L, L1);
+ L->destroyhook(L, L1);
luaF_close(L1, L1->stack); /* close all upvalues for this thread */
lua_assert(L1->openupval == NULL);
+ luai_userstatefree(L1);
freestack(L, L1);
- freestate(L, L1);
+ luaM_freemem(L, fromstate(L1), state_size(lua_State));
}
-LUA_API lua_State *lua_open (void) {
- lua_State *L = mallocstate(NULL);
- if (L) { /* allocation OK? */
- L->tt = LUA_TTHREAD;
- L->marked = 0;
- L->next = L->gclist = NULL;
- preinit_state(L);
- L->l_G = NULL;
- if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
- /* memory allocation error: free partial state */
- close_state(L);
- L = NULL;
- }
+LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
+ int i;
+ lua_State *L;
+ global_State *g;
+ void *l = (*f)(ud, NULL, 0, state_size(LG));
+ if (l == NULL) return NULL;
+ L = tostate(l);
+ g = &((LG *)L)->g;
+ L->next = NULL;
+ L->tt = LUA_TTHREAD;
+ g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);
+ L->marked = luaC_white(g);
+ set2bits(L->marked, FIXEDBIT, SFIXEDBIT);
+ preinit_state(L, g);
+ g->frealloc = f;
+ g->ud = ud;
+ g->mainthread = L;
+ g->uvhead.u.l.prev = &g->uvhead;
+ g->uvhead.u.l.next = &g->uvhead;
+ g->GCthreshold = 0; /* mark it as unfinished state */
+ g->strt.size = 0;
+ g->strt.nuse = 0;
+ g->strt.hash = NULL;
+ setnilvalue(registry(L));
+ luaZ_initbuffer(L, &g->buff);
+ g->panic = NULL;
+ g->gcstate = GCSpause;
+ g->rootgc = obj2gco(L);
+ g->sweepstrgc = 0;
+ g->sweepgc = &g->rootgc;
+ g->gray = NULL;
+ g->grayagain = NULL;
+ g->weak = NULL;
+ g->tmudata = NULL;
+ g->totalbytes = sizeof(LG);
+ g->gcpause = LUAI_GCPAUSE;
+ g->gcstepmul = LUAI_GCMUL;
+ g->gcdept = 0;
+ for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL;
+ if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
+ /* memory allocation error: free partial state */
+ close_state(L);
+ L = NULL;
}
- lua_userstateopen(L);
+ else
+ luai_userstateopen(L);
return L;
}
@@ -211,10 +205,10 @@ static void callallgcTM (lua_State *L, void *ud) {
LUA_API void lua_close (lua_State *L) {
- lua_lock(L);
L = G(L)->mainthread; /* only the main thread can be closed */
+ lua_lock(L);
luaF_close(L, L->stack); /* close all upvalues for this thread */
- luaC_separateudata(L); /* separate udata that have GC metamethods */
+ luaC_separateudata(L, 1); /* separate udata that have GC metamethods */
L->errfunc = 0; /* no error function during GC metamethods */
do { /* repeat until no more errors */
L->ci = L->base_ci;
@@ -222,6 +216,7 @@ LUA_API void lua_close (lua_State *L) {
L->nCcalls = 0;
} while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0);
lua_assert(G(L)->tmudata == NULL);
+ luai_userstateclose(L);
close_state(L);
}
diff --git a/lib/lua/src/lstring.c b/lib/lua/src/lstring.c
index 56df94e..f7b009f 100644
--- a/lib/lua/src/lstring.c
+++ b/lib/lua/src/lstring.c
@@ -1,5 +1,5 @@
/*
-** $Id: lstring.c,v 1.4 2004-11-27 21:46:07 pixel Exp $
+** $Id: lstring.c,v 1.5 2007-07-27 10:05:54 pixel Exp $
** String table (keeps all strings handled by Lua)
** See Copyright Notice in lua.h
*/
@@ -8,6 +8,7 @@
#include <string.h>
#define lstring_c
+#define LUA_CORE
#include "lua.h"
@@ -18,25 +19,23 @@
-void luaS_freeall (lua_State *L) {
- lua_assert(G(L)->strt.nuse==0);
- luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);
-}
-
-
void luaS_resize (lua_State *L, int newsize) {
- GCObject **newhash = luaM_newvector(L, newsize, GCObject *);
- stringtable *tb = &G(L)->strt;
+ GCObject **newhash;
+ stringtable *tb;
int i;
+ if (G(L)->gcstate == GCSsweepstring)
+ return; /* cannot resize during GC traverse */
+ newhash = luaM_newvector(L, newsize, GCObject *);
+ tb = &G(L)->strt;
for (i=0; i<newsize; i++) newhash[i] = NULL;
/* rehash */
for (i=0; i<tb->size; i++) {
GCObject *p = tb->hash[i];
while (p) { /* for each node in the list */
GCObject *next = p->gch.next; /* save next */
- lu_hash h = gcotots(p)->tsv.hash;
+ unsigned int h = gco2ts(p)->hash;
int h1 = lmod(h, newsize); /* new position */
- lua_assert(cast(int, h%newsize) == lmod(h, newsize));
+ lua_assert(cast_int(h%newsize) == lmod(h, newsize));
p->gch.next = newhash[h1]; /* chain it */
newhash[h1] = p;
p = next;
@@ -48,12 +47,16 @@ void luaS_resize (lua_State *L, int newsize) {
}
-static TString *newlstr (lua_State *L, const char *str, size_t l, lu_hash h) {
- TString *ts = cast(TString *, luaM_malloc(L, sizestring(l)));
+static TString *newlstr (lua_State *L, const char *str, size_t l,
+ unsigned int h) {
+ TString *ts;
stringtable *tb;
+ if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char))
+ luaM_toobig(L);
+ ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString)));
ts->tsv.len = l;
ts->tsv.hash = h;
- ts->tsv.marked = 0;
+ ts->tsv.marked = luaC_white(G(L));
ts->tsv.tt = LUA_TSTRING;
ts->tsv.reserved = 0;
memcpy(ts+1, str, l*sizeof(char));
@@ -61,9 +64,9 @@ static TString *newlstr (lua_State *L, const char *str, size_t l, lu_hash h) {
tb = &G(L)->strt;
h = lmod(h, tb->size);
ts->tsv.next = tb->hash[h]; /* chain new entry */
- tb->hash[h] = valtogco(ts);
+ tb->hash[h] = obj2gco(ts);
tb->nuse++;
- if (tb->nuse > cast(ls_nstr, tb->size) && tb->size <= MAX_INT/2)
+ if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
luaS_resize(L, tb->size*2); /* too crowded */
return ts;
}
@@ -71,32 +74,38 @@ static TString *newlstr (lua_State *L, const char *str, size_t l, lu_hash h) {
TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
GCObject *o;
- lu_hash h = (lu_hash)l; /* seed */
+ unsigned int h = cast(unsigned int, l); /* seed */
size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */
size_t l1;
for (l1=l; l1>=step; l1-=step) /* compute hash */
- h = h ^ ((h<<5)+(h>>2)+(unsigned char)(str[l1-1]));
+ h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1]));
for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)];
o != NULL;
o = o->gch.next) {
- TString *ts = gcotots(o);
- if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0))
+ TString *ts = rawgco2ts(o);
+ if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) {
+ /* string may be dead */
+ if (isdead(G(L), o)) changewhite(o);
return ts;
+ }
}
return newlstr(L, str, l, h); /* not found */
}
-Udata *luaS_newudata (lua_State *L, size_t s) {
+Udata *luaS_newudata (lua_State *L, size_t s, Table *e) {
Udata *u;
- u = cast(Udata *, luaM_malloc(L, sizeudata(s)));
- u->uv.marked = (1<<1); /* is not finalized */
+ if (s > MAX_SIZET - sizeof(Udata))
+ luaM_toobig(L);
+ u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata)));
+ u->uv.marked = luaC_white(G(L)); /* is not finalized */
u->uv.tt = LUA_TUSERDATA;
u->uv.len = s;
- u->uv.metatable = hvalue(defaultmeta(L));
- /* chain it on udata list */
- u->uv.next = G(L)->rootudata;
- G(L)->rootudata = valtogco(u);
+ u->uv.metatable = NULL;
+ u->uv.env = e;
+ /* chain it on udata list (after main thread) */
+ u->uv.next = G(L)->mainthread->next;
+ G(L)->mainthread->next = obj2gco(u);
return u;
}
diff --git a/lib/lua/src/ltable.c b/lib/lua/src/ltable.c
index 4969d84..62d757a 100644
--- a/lib/lua/src/ltable.c
+++ b/lib/lua/src/ltable.c
@@ -1,5 +1,5 @@
/*
-** $Id: ltable.c,v 1.4 2004-11-27 21:46:07 pixel Exp $
+** $Id: ltable.c,v 1.5 2007-07-27 10:05:54 pixel Exp $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
@@ -15,15 +15,14 @@
** A main invariant of these tables is that, if an element is not
** in its main position (i.e. the `original' position that its hash gives
** to it), then the colliding element is in its own main position.
-** In other words, there are collisions only when two elements have the
-** same main position (i.e. the same hash values for that table size).
-** Because of that, the load factor of these tables can be 100% without
-** performance penalties.
+** Hence even when the load factor reaches 100%, performance remains good.
*/
+#include <math.h>
#include <string.h>
#define ltable_c
+#define LUA_CORE
#include "lua.h"
@@ -39,20 +38,13 @@
/*
** max size of array part is 2^MAXBITS
*/
-#if BITS_INT > 26
-#define MAXBITS 24
+#if LUAI_BITSINT > 26
+#define MAXBITS 26
#else
-#define MAXBITS (BITS_INT-2)
+#define MAXBITS (LUAI_BITSINT-2)
#endif
-/* check whether `x' < 2^MAXBITS */
-#define toobig(x) ((((x)-1) >> MAXBITS) != 0)
-
-
-/* function to convert a lua_Number to int (with any rounding method) */
-#ifndef lua_number2int
-#define lua_number2int(i,n) ((i)=(int)(n))
-#endif
+#define MAXASIZE (1 << MAXBITS)
#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t))))
@@ -74,7 +66,16 @@
/*
** number of ints inside a lua_Number
*/
-#define numints cast(int, sizeof(lua_Number)/sizeof(int))
+#define numints cast_int(sizeof(lua_Number)/sizeof(int))
+
+
+
+#define dummynode (&dummynode_)
+
+static const Node dummynode_ = {
+ {{NULL}, LUA_TNIL}, /* value */
+ {{{NULL}, LUA_TNIL, NULL}} /* key */
+};
/*
@@ -87,7 +88,7 @@ static Node *hashnum (const Table *t, lua_Number n) {
lua_assert(sizeof(a) <= sizeof(n));
memcpy(a, &n, sizeof(a));
for (i = 1; i < numints; i++) a[0] += a[i];
- return hashmod(t, cast(lu_hash, a[0]));
+ return hashmod(t, a[0]);
}
@@ -96,12 +97,12 @@ static Node *hashnum (const Table *t, lua_Number n) {
** returns the `main' position of an element in a table (that is, the index
** of its hash value)
*/
-Node *luaH_mainposition (const Table *t, const TObject *key) {
+static Node *mainposition (const Table *t, const TValue *key) {
switch (ttype(key)) {
case LUA_TNUMBER:
return hashnum(t, nvalue(key));
case LUA_TSTRING:
- return hashstr(t, tsvalue(key));
+ return hashstr(t, rawtsvalue(key));
case LUA_TBOOLEAN:
return hashboolean(t, bvalue(key));
case LUA_TLIGHTUSERDATA:
@@ -116,11 +117,12 @@ Node *luaH_mainposition (const Table *t, const TObject *key) {
** returns the index for `key' if `key' is an appropriate key to live in
** the array part of the table, -1 otherwise.
*/
-static int arrayindex (const TObject *key) {
+static int arrayindex (const TValue *key) {
if (ttisnumber(key)) {
+ lua_Number n = nvalue(key);
int k;
- lua_number2int(k, (nvalue(key)));
- if (cast(lua_Number, k) == nvalue(key) && k >= 1 && !toobig(k))
+ lua_number2int(k, n);
+ if (luai_numeq(cast_num(k), n))
return k;
}
return -1; /* `key' did not match some condition */
@@ -130,39 +132,46 @@ static int arrayindex (const TObject *key) {
/*
** returns the index of a `key' for table traversals. First goes all
** elements in the array part, then elements in the hash part. The
-** beginning and end of a traversal are signalled by -1.
+** beginning of a traversal is signalled by -1.
*/
-static int luaH_index (lua_State *L, Table *t, StkId key) {
+static int findindex (lua_State *L, Table *t, StkId key) {
int i;
if (ttisnil(key)) return -1; /* first iteration */
i = arrayindex(key);
- if (0 <= i && i <= t->sizearray) { /* is `key' inside array part? */
+ if (0 < i && i <= t->sizearray) /* is `key' inside array part? */
return i-1; /* yes; that's the index (corrected to C) */
- }
else {
- const TObject *v = luaH_get(t, key);
- if (v == &luaO_nilobject)
- luaG_runerror(L, "invalid key for `next'");
- i = cast(int, (cast(const lu_byte *, v) -
- cast(const lu_byte *, gval(gnode(t, 0)))) / sizeof(Node));
- return i + t->sizearray; /* hash elements are numbered after array ones */
+ Node *n = mainposition(t, key);
+ do { /* check whether `key' is somewhere in the chain */
+ /* key may be dead already, but it is ok to use it in `next' */
+ if (luaO_rawequalObj(key2tval(n), key) ||
+ (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) &&
+ gcvalue(gkey(n)) == gcvalue(key))) {
+ i = cast_int(n - gnode(t, 0)); /* key index in hash table */
+ /* hash elements are numbered after array ones */
+ return i + t->sizearray;
+ }
+ else n = gnext(n);
+ } while (n);
+ luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */
+ return 0; /* to avoid warnings */
}
}
int luaH_next (lua_State *L, Table *t, StkId key) {
- int i = luaH_index(L, t, key); /* find original element */
+ int i = findindex(L, t, key); /* find original element */
for (i++; i < t->sizearray; i++) { /* try first array part */
if (!ttisnil(&t->array[i])) { /* a non-nil value? */
- setnvalue(key, cast(lua_Number, i+1));
- setobj2s(key+1, &t->array[i]);
+ setnvalue(key, cast_num(i+1));
+ setobj2s(L, key+1, &t->array[i]);
return 1;
}
}
for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */
if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */
- setobj2s(key, gkey(gnode(t, i)));
- setobj2s(key+1, gval(gnode(t, i)));
+ setobj2s(L, key, key2tval(gnode(t, i)));
+ setobj2s(L, key+1, gval(gnode(t, i)));
return 1;
}
}
@@ -177,95 +186,111 @@ int luaH_next (lua_State *L, Table *t, StkId key) {
*/
-static void computesizes (int nums[], int ntotal, int *narray, int *nhash) {
+static int computesizes (int nums[], int *narray) {
int i;
- int a = nums[0]; /* number of elements smaller than 2^i */
- int na = a; /* number of elements to go to array part */
- int n = (na == 0) ? -1 : 0; /* (log of) optimal size for array part */
- for (i = 1; a < *narray && *narray >= twoto(i-1); i++) {
+ int twotoi; /* 2^i */
+ int a = 0; /* number of elements smaller than 2^i */
+ int na = 0; /* number of elements to go to array part */
+ int n = 0; /* optimal size for array part */
+ for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) {
if (nums[i] > 0) {
a += nums[i];
- if (a >= twoto(i-1)) { /* more than half elements in use? */
- n = i;
- na = a;
+ if (a > twotoi/2) { /* more than half elements present? */
+ n = twotoi; /* optimal size (till now) */
+ na = a; /* all elements smaller than n will go to array part */
}
}
+ if (a == *narray) break; /* all elements already counted */
}
- lua_assert(na <= *narray && *narray <= ntotal);
- *nhash = ntotal - na;
- *narray = (n == -1) ? 0 : twoto(n);
- lua_assert(na <= *narray && na >= *narray/2);
+ *narray = n;
+ lua_assert(*narray/2 <= na && na <= *narray);
+ return na;
}
-static void numuse (const Table *t, int *narray, int *nhash) {
- int nums[MAXBITS+1];
- int i, lg;
- int totaluse = 0;
- /* count elements in array part */
- for (i=0, lg=0; lg<=MAXBITS; lg++) { /* for each slice [2^(lg-1) to 2^lg) */
- int ttlg = twoto(lg); /* 2^lg */
- if (ttlg > t->sizearray) {
- ttlg = t->sizearray;
- if (i >= ttlg) break;
+static int countint (const TValue *key, int *nums) {
+ int k = arrayindex(key);
+ if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */
+ nums[ceillog2(k)]++; /* count as such */
+ return 1;
+ }
+ else
+ return 0;
+}
+
+
+static int numusearray (const Table *t, int *nums) {
+ int lg;
+ int ttlg; /* 2^lg */
+ int ause = 0; /* summation of `nums' */
+ int i = 1; /* count to traverse all array keys */
+ for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */
+ int lc = 0; /* counter */
+ int lim = ttlg;
+ if (lim > t->sizearray) {
+ lim = t->sizearray; /* adjust upper limit */
+ if (i > lim)
+ break; /* no more elements to count */
}
- nums[lg] = 0;
- for (; i<ttlg; i++) {
- if (!ttisnil(&t->array[i])) {
- nums[lg]++;
- totaluse++;
- }
+ /* count elements in range (2^(lg-1), 2^lg] */
+ for (; i <= lim; i++) {
+ if (!ttisnil(&t->array[i-1]))
+ lc++;
}
+ nums[lg] += lc;
+ ause += lc;
}
- for (; lg<=MAXBITS; lg++) nums[lg] = 0; /* reset other counts */
- *narray = totaluse; /* all previous uses were in array part */
- /* count elements in hash part */
- i = sizenode(t);
+ return ause;
+}
+
+
+static int numusehash (const Table *t, int *nums, int *pnasize) {
+ int totaluse = 0; /* total number of elements */
+ int ause = 0; /* summation of `nums' */
+ int i = sizenode(t);
while (i--) {
Node *n = &t->node[i];
if (!ttisnil(gval(n))) {
- int k = arrayindex(gkey(n));
- if (k >= 0) { /* is `key' an appropriate array index? */
- nums[luaO_log2(k-1)+1]++; /* count as such */
- (*narray)++;
- }
+ ause += countint(key2tval(n), nums);
totaluse++;
}
}
- computesizes(nums, totaluse, narray, nhash);
+ *pnasize += ause;
+ return totaluse;
}
static void setarrayvector (lua_State *L, Table *t, int size) {
int i;
- luaM_reallocvector(L, t->array, t->sizearray, size, TObject);
+ luaM_reallocvector(L, t->array, t->sizearray, size, TValue);
for (i=t->sizearray; i<size; i++)
setnilvalue(&t->array[i]);
t->sizearray = size;
}
-static void setnodevector (lua_State *L, Table *t, int lsize) {
- int i;
- int size = twoto(lsize);
- if (lsize > MAXBITS)
- luaG_runerror(L, "table overflow");
- if (lsize == 0) { /* no elements to hash part? */
- t->node = G(L)->dummynode; /* use common `dummynode' */
- lua_assert(ttisnil(gkey(t->node))); /* assert invariants: */
- lua_assert(ttisnil(gval(t->node)));
- lua_assert(t->node->next == NULL); /* (`dummynode' must be empty) */
+static void setnodevector (lua_State *L, Table *t, int size) {
+ int lsize;
+ if (size == 0) { /* no elements to hash part? */
+ t->node = cast(Node *, dummynode); /* use common `dummynode' */
+ lsize = 0;
}
else {
+ int i;
+ lsize = ceillog2(size);
+ if (lsize > MAXBITS)
+ luaG_runerror(L, "table overflow");
+ size = twoto(lsize);
t->node = luaM_newvector(L, size, Node);
for (i=0; i<size; i++) {
- t->node[i].next = NULL;
- setnilvalue(gkey(gnode(t, i)));
- setnilvalue(gval(gnode(t, i)));
+ Node *n = gnode(t, i);
+ gnext(n) = NULL;
+ setnilvalue(gkey(n));
+ setnilvalue(gval(n));
}
}
- t->lsizenode = cast(lu_byte, lsize);
- t->firstfree = gnode(t, size-1); /* first free position to be used */
+ t->lsizenode = cast_byte(lsize);
+ t->lastfree = gnode(t, size); /* all positions are free */
}
@@ -273,48 +298,54 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
int i;
int oldasize = t->sizearray;
int oldhsize = t->lsizenode;
- Node *nold;
- Node temp[1];
- if (oldhsize)
- nold = t->node; /* save old hash ... */
- else { /* old hash is `dummynode' */
- lua_assert(t->node == G(L)->dummynode);
- temp[0] = t->node[0]; /* copy it to `temp' */
- nold = temp;
- setnilvalue(gkey(G(L)->dummynode)); /* restate invariant */
- setnilvalue(gval(G(L)->dummynode));
- lua_assert(G(L)->dummynode->next == NULL);
- }
+ Node *nold = t->node; /* save old hash ... */
if (nasize > oldasize) /* array part must grow? */
setarrayvector(L, t, nasize);
/* create new hash part with appropriate size */
setnodevector(L, t, nhsize);
- /* re-insert elements */
if (nasize < oldasize) { /* array part must shrink? */
t->sizearray = nasize;
/* re-insert elements from vanishing slice */
for (i=nasize; i<oldasize; i++) {
if (!ttisnil(&t->array[i]))
- setobjt2t(luaH_setnum(L, t, i+1), &t->array[i]);
+ setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]);
}
/* shrink array */
- luaM_reallocvector(L, t->array, oldasize, nasize, TObject);
+ luaM_reallocvector(L, t->array, oldasize, nasize, TValue);
}
- /* re-insert elements in hash part */
+ /* re-insert elements from hash part */
for (i = twoto(oldhsize) - 1; i >= 0; i--) {
Node *old = nold+i;
if (!ttisnil(gval(old)))
- setobjt2t(luaH_set(L, t, gkey(old)), gval(old));
+ setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old));
}
- if (oldhsize)
+ if (nold != dummynode)
luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */
}
-static void rehash (lua_State *L, Table *t) {
- int nasize, nhsize;
- numuse(t, &nasize, &nhsize); /* compute new sizes for array and hash parts */
- resize(L, t, nasize, luaO_log2(nhsize)+1);
+void luaH_resizearray (lua_State *L, Table *t, int nasize) {
+ int nsize = (t->node == dummynode) ? 0 : sizenode(t);
+ resize(L, t, nasize, nsize);
+}
+
+
+static void rehash (lua_State *L, Table *t, const TValue *ek) {
+ int nasize, na;
+ int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */
+ int i;
+ int totaluse;
+ for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */
+ nasize = numusearray(t, nums); /* count keys in array part */
+ totaluse = nasize; /* all those keys are integer keys */
+ totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */
+ /* count extra key */
+ nasize += countint(ek, nums);
+ totaluse++;
+ /* compute new size for array part */
+ na = computesizes(nums, &nasize);
+ /* resize the table to new computed sizes */
+ resize(L, t, nasize, totaluse - na);
}
@@ -324,49 +355,38 @@ static void rehash (lua_State *L, Table *t) {
*/
-Table *luaH_new (lua_State *L, int narray, int lnhash) {
+Table *luaH_new (lua_State *L, int narray, int nhash) {
Table *t = luaM_new(L, Table);
- luaC_link(L, valtogco(t), LUA_TTABLE);
- t->metatable = hvalue(defaultmeta(L));
- t->flags = cast(lu_byte, ~0);
+ luaC_link(L, obj2gco(t), LUA_TTABLE);
+ t->metatable = NULL;
+ t->flags = cast_byte(~0);
/* temporary values (kept only if some malloc fails) */
t->array = NULL;
t->sizearray = 0;
t->lsizenode = 0;
- t->node = NULL;
+ t->node = cast(Node *, dummynode);
setarrayvector(L, t, narray);
- setnodevector(L, t, lnhash);
+ setnodevector(L, t, nhash);
return t;
}
void luaH_free (lua_State *L, Table *t) {
- if (t->lsizenode)
+ if (t->node != dummynode)
luaM_freearray(L, t->node, sizenode(t), Node);
- luaM_freearray(L, t->array, t->sizearray, TObject);
- luaM_freelem(L, t);
+ luaM_freearray(L, t->array, t->sizearray, TValue);
+ luaM_free(L, t);
}
-#if 0
-/*
-** try to remove an element from a hash table; cannot move any element
-** (because gc can call `remove' during a table traversal)
-*/
-void luaH_remove (Table *t, Node *e) {
- Node *mp = luaH_mainposition(t, gkey(e));
- if (e != mp) { /* element not in its main position? */
- while (mp->next != e) mp = mp->next; /* find previous */
- mp->next = e->next; /* remove `e' from its list */
- }
- else {
- if (e->next != NULL) ??
+static Node *getfreepos (Table *t) {
+ while (t->lastfree-- > t->node) {
+ if (ttisnil(gkey(t->lastfree)))
+ return t->lastfree;
}
- lua_assert(ttisnil(gval(node)));
- setnilvalue(gkey(e)); /* clear node `e' */
- e->next = NULL;
+ return NULL; /* could not find a free place */
}
-#endif
+
/*
@@ -376,76 +396,55 @@ void luaH_remove (Table *t, Node *e) {
** put new key in its main position; otherwise (colliding node is in its main
** position), new key goes to an empty position.
*/
-static TObject *newkey (lua_State *L, Table *t, const TObject *key) {
- TObject *val;
- Node *mp = luaH_mainposition(t, key);
- if (!ttisnil(gval(mp))) { /* main position is not free? */
- Node *othern = luaH_mainposition(t, gkey(mp)); /* `mp' of colliding node */
- Node *n = t->firstfree; /* get a free place */
+static TValue *newkey (lua_State *L, Table *t, const TValue *key) {
+ Node *mp = mainposition(t, key);
+ if (!ttisnil(gval(mp)) || mp == dummynode) {
+ Node *othern;
+ Node *n = getfreepos(t); /* get a free place */
+ if (n == NULL) { /* cannot find a free place? */
+ rehash(L, t, key); /* grow table */
+ return luaH_set(L, t, key); /* re-insert key into grown table */
+ }
+ lua_assert(n != dummynode);
+ othern = mainposition(t, key2tval(mp));
if (othern != mp) { /* is colliding node out of its main position? */
/* yes; move colliding node into free position */
- while (othern->next != mp) othern = othern->next; /* find previous */
- othern->next = n; /* redo the chain with `n' in place of `mp' */
+ while (gnext(othern) != mp) othern = gnext(othern); /* find previous */
+ gnext(othern) = n; /* redo the chain with `n' in place of `mp' */
*n = *mp; /* copy colliding node into free pos. (mp->next also goes) */
- mp->next = NULL; /* now `mp' is free */
+ gnext(mp) = NULL; /* now `mp' is free */
setnilvalue(gval(mp));
}
else { /* colliding node is in its own main position */
/* new node will go into free position */
- n->next = mp->next; /* chain new position */
- mp->next = n;
+ gnext(n) = gnext(mp); /* chain new position */
+ gnext(mp) = n;
mp = n;
}
}
- setobj2t(gkey(mp), key); /* write barrier */
+ gkey(mp)->value = key->value; gkey(mp)->tt = key->tt;
+ luaC_barriert(L, t, key);
lua_assert(ttisnil(gval(mp)));
- for (;;) { /* correct `firstfree' */
- if (ttisnil(gkey(t->firstfree)))
- return gval(mp); /* OK; table still has a free place */
- else if (t->firstfree == t->node) break; /* cannot decrement from here */
- else (t->firstfree)--;
- }
- /* no more free places; must create one */
- setbvalue(gval(mp), 0); /* avoid new key being removed */
- rehash(L, t); /* grow table */
- val = cast(TObject *, luaH_get(t, key)); /* get new position */
- lua_assert(ttisboolean(val));
- setnilvalue(val);
- return val;
-}
-
-
-/*
-** generic search function
-*/
-static const TObject *luaH_getany (Table *t, const TObject *key) {
- if (ttisnil(key)) return &luaO_nilobject;
- else {
- Node *n = luaH_mainposition(t, key);
- do { /* check whether `key' is somewhere in the chain */
- if (luaO_rawequalObj(gkey(n), key)) return gval(n); /* that's it */
- else n = n->next;
- } while (n);
- return &luaO_nilobject;
- }
+ return gval(mp);
}
/*
** search function for integers
*/
-const TObject *luaH_getnum (Table *t, int key) {
- if (1 <= key && key <= t->sizearray)
+const TValue *luaH_getnum (Table *t, int key) {
+ /* (1 <= key && key <= t->sizearray) */
+ if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))
return &t->array[key-1];
else {
- lua_Number nk = cast(lua_Number, key);
+ lua_Number nk = cast_num(key);
Node *n = hashnum(t, nk);
do { /* check whether `key' is somewhere in the chain */
- if (ttisnumber(gkey(n)) && nvalue(gkey(n)) == nk)
+ if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk))
return gval(n); /* that's it */
- else n = n->next;
+ else n = gnext(n);
} while (n);
- return &luaO_nilobject;
+ return luaO_nilobject;
}
}
@@ -453,57 +452,137 @@ const TObject *luaH_getnum (Table *t, int key) {
/*
** search function for strings
*/
-const TObject *luaH_getstr (Table *t, TString *key) {
+const TValue *luaH_getstr (Table *t, TString *key) {
Node *n = hashstr(t, key);
do { /* check whether `key' is somewhere in the chain */
- if (ttisstring(gkey(n)) && tsvalue(gkey(n)) == key)
+ if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key)
return gval(n); /* that's it */
- else n = n->next;
+ else n = gnext(n);
} while (n);
- return &luaO_nilobject;
+ return luaO_nilobject;
}
/*
** main search function
*/
-const TObject *luaH_get (Table *t, const TObject *key) {
+const TValue *luaH_get (Table *t, const TValue *key) {
switch (ttype(key)) {
- case LUA_TSTRING: return luaH_getstr(t, tsvalue(key));
+ case LUA_TNIL: return luaO_nilobject;
+ case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));
case LUA_TNUMBER: {
int k;
- lua_number2int(k, (nvalue(key)));
- if (cast(lua_Number, k) == nvalue(key)) /* is an integer index? */
+ lua_Number n = nvalue(key);
+ lua_number2int(k, n);
+ if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */
return luaH_getnum(t, k); /* use specialized version */
/* else go through */
}
- default: return luaH_getany(t, key);
+ default: {
+ Node *n = mainposition(t, key);
+ do { /* check whether `key' is somewhere in the chain */
+ if (luaO_rawequalObj(key2tval(n), key))
+ return gval(n); /* that's it */
+ else n = gnext(n);
+ } while (n);
+ return luaO_nilobject;
+ }
}
}
-TObject *luaH_set (lua_State *L, Table *t, const TObject *key) {
- const TObject *p = luaH_get(t, key);
+TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
+ const TValue *p = luaH_get(t, key);
t->flags = 0;
- if (p != &luaO_nilobject)
- return cast(TObject *, p);
+ if (p != luaO_nilobject)
+ return cast(TValue *, p);
else {
if (ttisnil(key)) luaG_runerror(L, "table index is nil");
- else if (ttisnumber(key) && nvalue(key) != nvalue(key))
+ else if (ttisnumber(key) && luai_numisnan(nvalue(key)))
luaG_runerror(L, "table index is NaN");
return newkey(L, t, key);
}
}
-TObject *luaH_setnum (lua_State *L, Table *t, int key) {
- const TObject *p = luaH_getnum(t, key);
- if (p != &luaO_nilobject)
- return cast(TObject *, p);
+TValue *luaH_setnum (lua_State *L, Table *t, int key) {
+ const TValue *p = luaH_getnum(t, key);
+ if (p != luaO_nilobject)
+ return cast(TValue *, p);
else {
- TObject k;
- setnvalue(&k, cast(lua_Number, key));
+ TValue k;
+ setnvalue(&k, cast_num(key));
return newkey(L, t, &k);
}
}
+
+TValue *luaH_setstr (lua_State *L, Table *t, TString *key) {
+ const TValue *p = luaH_getstr(t, key);
+ if (p != luaO_nilobject)
+ return cast(TValue *, p);
+ else {
+ TValue k;
+ setsvalue(L, &k, key);
+ return newkey(L, t, &k);
+ }
+}
+
+
+static int unbound_search (Table *t, unsigned int j) {
+ unsigned int i = j; /* i is zero or a present index */
+ j++;
+ /* find `i' and `j' such that i is present and j is not */
+ while (!ttisnil(luaH_getnum(t, j))) {
+ i = j;
+ j *= 2;
+ if (j > cast(unsigned int, MAX_INT)) { /* overflow? */
+ /* table was built with bad purposes: resort to linear search */
+ i = 1;
+ while (!ttisnil(luaH_getnum(t, i))) i++;
+ return i - 1;
+ }
+ }
+ /* now do a binary search between them */
+ while (j - i > 1) {
+ unsigned int m = (i+j)/2;
+ if (ttisnil(luaH_getnum(t, m))) j = m;
+ else i = m;
+ }
+ return i;
+}
+
+
+/*
+** Try to find a boundary in table `t'. A `boundary' is an integer index
+** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
+*/
+int luaH_getn (Table *t) {
+ unsigned int j = t->sizearray;
+ if (j > 0 && ttisnil(&t->array[j - 1])) {
+ /* there is a boundary in the array part: (binary) search for it */
+ unsigned int i = 0;
+ while (j - i > 1) {
+ unsigned int m = (i+j)/2;
+ if (ttisnil(&t->array[m - 1])) j = m;
+ else i = m;
+ }
+ return i;
+ }
+ /* else must find a boundary in hash part */
+ else if (t->node == dummynode) /* hash part is empty? */
+ return j; /* that is easy... */
+ else return unbound_search(t, j);
+}
+
+
+
+#if defined(LUA_DEBUG)
+
+Node *luaH_mainposition (const Table *t, const TValue *key) {
+ return mainposition(t, key);
+}
+
+int luaH_isdummy (Node *n) { return n == dummynode; }
+
+#endif
diff --git a/lib/lua/src/ltm.c b/lib/lua/src/ltm.c
index 5ad7858..2fcb68c 100644
--- a/lib/lua/src/ltm.c
+++ b/lib/lua/src/ltm.c
@@ -1,5 +1,5 @@
/*
-** $Id: ltm.c,v 1.4 2004-11-27 21:46:07 pixel Exp $
+** $Id: ltm.c,v 1.5 2007-07-27 10:05:54 pixel Exp $
** Tag methods
** See Copyright Notice in lua.h
*/
@@ -8,6 +8,7 @@
#include <string.h>
#define ltm_c
+#define LUA_CORE
#include "lua.h"
@@ -21,7 +22,8 @@
const char *const luaT_typenames[] = {
"nil", "boolean", "userdata", "number",
- "string", "table", "function", "userdata", "thread"
+ "string", "table", "function", "userdata", "thread",
+ "proto", "upval"
};
@@ -29,8 +31,8 @@ void luaT_init (lua_State *L) {
static const char *const luaT_eventname[] = { /* ORDER TM */
"__index", "__newindex",
"__gc", "__mode", "__eq",
- "__add", "__sub", "__mul", "__div",
- "__pow", "__unm", "__lt", "__le",
+ "__add", "__sub", "__mul", "__div", "__mod",
+ "__pow", "__unm", "__len", "__lt", "__le",
"__concat", "__call"
};
int i;
@@ -45,26 +47,29 @@ void luaT_init (lua_State *L) {
** function to be used with macro "fasttm": optimized for absence of
** tag methods
*/
-const TObject *luaT_gettm (Table *events, TMS event, TString *ename) {
- const TObject *tm = luaH_getstr(events, ename);
+const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
+ const TValue *tm = luaH_getstr(events, ename);
lua_assert(event <= TM_EQ);
if (ttisnil(tm)) { /* no tag method? */
- events->flags |= cast(lu_byte, 1u<<event); /* cache this fact */
+ events->flags |= cast_byte(1u<<event); /* cache this fact */
return NULL;
}
else return tm;
}
-const TObject *luaT_gettmbyobj (lua_State *L, const TObject *o, TMS event) {
- TString *ename = G(L)->tmname[event];
+const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
+ Table *mt;
switch (ttype(o)) {
case LUA_TTABLE:
- return luaH_getstr(hvalue(o)->metatable, ename);
+ mt = hvalue(o)->metatable;
+ break;
case LUA_TUSERDATA:
- return luaH_getstr(uvalue(o)->uv.metatable, ename);
+ mt = uvalue(o)->metatable;
+ break;
default:
- return &luaO_nilobject;
+ mt = G(L)->mt[ttype(o)];
}
+ return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject);
}
diff --git a/lib/lua/src/luacomp.c b/lib/lua/src/luacomp.c
index 0009b24..1246869 100644
--- a/lib/lua/src/luacomp.c
+++ b/lib/lua/src/luacomp.c
@@ -1,5 +1,5 @@
/*
- ** $Id: luacomp.c,v 1.7 2004-12-27 19:52:24 pixel Exp $
+ ** $Id: luacomp.c,v 1.8 2007-07-27 10:05:54 pixel Exp $
** Lua compiler (saves bytecodes to files; also list bytecodes)
** Highly hacked by Nicolas "Pixel" Noble to be transformed into a
** small form-factor LUA compiler.
@@ -19,6 +19,7 @@
#include "lopcodes.h"
#include "lstring.h"
#include "lundump.h"
+#include "ldo.h"
#ifndef PROGNAME
#define PROGNAME "luacomp" /* program name */
@@ -26,27 +27,26 @@
const char * progname = PROGNAME; /* actual program name */
-static Proto * toproto(lua_State * L, int i) {
- const Closure * c = (const Closure *) lua_topointer(L, i);
+#define toproto(L, i) (clvalue(L->top + (i))->l.p)
- return c->l.p;
-}
-
-static Proto * combine(lua_State * L, int n) {
+static const Proto * combine(lua_State * L, int n) {
if (n == 1)
return toproto(L, -1);
else {
int i, pc = 0;
Proto * f = luaF_newproto(L);
+ setptvalue2s(L, L->top, f); incr_top(L);
f->source = luaS_newliteral(L, "=(" PROGNAME ")");
f->maxstacksize = 1;
+ pc = 2 * n + 1;
+ f->code = luaM_newvector(L, pc, Instruction);
+ f->sizecode = pc;
f->p = luaM_newvector(L, n, Proto *);
f->sizep = n;
- f->sizecode = 2 * n + 1;
- f->code = luaM_newvector(L, f->sizecode, Instruction);
+ pc = 0;
for (i = 0; i < n; i++) {
- f->p[i] = toproto(L, i - n);
+ f->p[i] = toproto(L, i - n - 1);
f->code[pc++] = CREATE_ABx(OP_CLOSURE, 0, i);
f->code[pc++] = CREATE_ABC(OP_CALL, 0, 1, 1);
}
@@ -55,30 +55,13 @@ static Proto * combine(lua_State * L, int n) {
}
}
-static void strip(lua_State * L, Proto * f) {
- int i, n = f->sizep;
- luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);
- luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
-
- luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);
- f->lineinfo = NULL;
- f->sizelineinfo = 0;
- f->locvars = NULL;
- f->sizelocvars = 0;
- f->upvalues = NULL;
- f->sizeupvalues = 0;
- f->source = luaS_newliteral(L, "=(none)");
- for (i = 0; i < n; i++)
- strip(L, f->p[i]);
-}
-
-void luacmain(lua_State * L, int stripping, lua_Chunkwriter w, void *uD) {
+void luacmain(lua_State * L, int stripping, lua_Chunkwriter w, void *uD, int listing) {
Proto * f;
f = combine(L, lua_gettop(L));
- if (stripping)
- strip(L, f);
+ if (listing)
+ luaU_print(f, listing > 1);
lua_lock(L);
- luaU_dump(L, f, w, uD);
+ luaU_dump(L, f, w, uD, stripping);
lua_unlock(L);
}
diff --git a/lib/lua/src/lundump.c b/lib/lua/src/lundump.c
index 7d9f031..a8692a8 100644
--- a/lib/lua/src/lundump.c
+++ b/lib/lua/src/lundump.c
@@ -1,286 +1,223 @@
/*
-** $Id: lundump.c,v 1.4 2004-11-27 21:46:07 pixel Exp $
-** load pre-compiled Lua chunks
+** $Id: lundump.c,v 1.5 2007-07-27 10:05:54 pixel Exp $
+** load precompiled Lua chunks
** See Copyright Notice in lua.h
*/
+#include <string.h>
+
#define lundump_c
+#define LUA_CORE
#include "lua.h"
#include "ldebug.h"
+#include "ldo.h"
#include "lfunc.h"
#include "lmem.h"
-#include "lopcodes.h"
+#include "lobject.h"
#include "lstring.h"
#include "lundump.h"
#include "lzio.h"
-#define LoadByte (lu_byte) ezgetc
-
typedef struct {
lua_State* L;
ZIO* Z;
Mbuffer* b;
- int swap;
const char* name;
} LoadState;
-static void unexpectedEOZ (LoadState* S)
-{
- luaG_runerror(S->L,"unexpected end of file in %s",S->name);
-}
+#ifdef LUAC_TRUST_BINARIES
+#define IF(c,s)
+#else
+#define IF(c,s) if (c) error(S,s)
-static int ezgetc (LoadState* S)
+static void error(LoadState* S, const char* why)
{
- int c=zgetc(S->Z);
- if (c==EOZ) unexpectedEOZ(S);
- return c;
+ luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why);
+ luaD_throw(S->L,LUA_ERRSYNTAX);
}
+#endif
-static void ezread (LoadState* S, void* b, int n)
-{
- int r=luaZ_read(S->Z,b,n);
- if (r!=0) unexpectedEOZ(S);
-}
+#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size))
+#define LoadByte(S) (lu_byte)LoadChar(S)
+#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x))
+#define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
-static void LoadBlock (LoadState* S, void* b, size_t size)
+static void LoadBlock(LoadState* S, void* b, size_t size)
{
- if (S->swap)
- {
- char* p=(char*) b+size-1;
- int n=size;
- while (n--) *p--=(char)ezgetc(S);
- }
- else
- ezread(S,b,size);
+ size_t r=luaZ_read(S->Z,b,size);
+ IF (r!=0, "unexpected end");
}
-static void LoadVector (LoadState* S, void* b, int m, size_t size)
+static int LoadChar(LoadState* S)
{
- if (S->swap)
- {
- char* q=(char*) b;
- while (m--)
- {
- char* p=q+size-1;
- int n=size;
- while (n--) *p--=(char)ezgetc(S);
- q+=size;
- }
- }
- else
- ezread(S,b,m*size);
-}
-
-static int LoadInt (LoadState* S)
-{
- int x;
- LoadBlock(S,&x,sizeof(x));
- if (x<0) luaG_runerror(S->L,"bad integer in %s",S->name);
+ char x;
+ LoadVar(S,x);
return x;
}
-static size_t LoadSize (LoadState* S)
+static int LoadInt(LoadState* S)
{
- size_t x;
- LoadBlock(S,&x,sizeof(x));
+ int x;
+ LoadVar(S,x);
+ IF (x<0, "bad integer");
return x;
}
-static lua_Number LoadNumber (LoadState* S)
+static lua_Number LoadNumber(LoadState* S)
{
lua_Number x;
- LoadBlock(S,&x,sizeof(x));
+ LoadVar(S,x);
return x;
}
-static TString* LoadString (LoadState* S)
+static TString* LoadString(LoadState* S)
{
- size_t size=LoadSize(S);
+ size_t size;
+ LoadVar(S,size);
if (size==0)
return NULL;
else
{
char* s=luaZ_openspace(S->L,S->b,size);
- ezread(S,s,size);
+ LoadBlock(S,s,size);
return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
}
}
-static void LoadCode (LoadState* S, Proto* f)
+static void LoadCode(LoadState* S, Proto* f)
{
- int size=LoadInt(S);
- f->code=luaM_newvector(S->L,size,Instruction);
- f->sizecode=size;
- LoadVector(S,f->code,size,sizeof(*f->code));
-}
-
-static void LoadLocals (LoadState* S, Proto* f)
-{
- int i,n;
- n=LoadInt(S);
- f->locvars=luaM_newvector(S->L,n,LocVar);
- f->sizelocvars=n;
- for (i=0; i<n; i++)
- {
- f->locvars[i].varname=LoadString(S);
- f->locvars[i].startpc=LoadInt(S);
- f->locvars[i].endpc=LoadInt(S);
- }
-}
-
-static void LoadLines (LoadState* S, Proto* f)
-{
- int size=LoadInt(S);
- f->lineinfo=luaM_newvector(S->L,size,int);
- f->sizelineinfo=size;
- LoadVector(S,f->lineinfo,size,sizeof(*f->lineinfo));
-}
-
-static void LoadUpvalues (LoadState* S, Proto* f)
-{
- int i,n;
- n=LoadInt(S);
- if (n!=0 && n!=f->nups)
- luaG_runerror(S->L,"bad nupvalues in %s: read %d; expected %d",
- S->name,n,f->nups);
- f->upvalues=luaM_newvector(S->L,n,TString*);
- f->sizeupvalues=n;
- for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);
+ int n=LoadInt(S);
+ f->code=luaM_newvector(S->L,n,Instruction);
+ f->sizecode=n;
+ LoadVector(S,f->code,n,sizeof(Instruction));
}
-static Proto* LoadFunction (LoadState* S, TString* p);
+static Proto* LoadFunction(LoadState* S, TString* p);
-static void LoadConstants (LoadState* S, Proto* f)
+static void LoadConstants(LoadState* S, Proto* f)
{
int i,n;
n=LoadInt(S);
- f->k=luaM_newvector(S->L,n,TObject);
+ f->k=luaM_newvector(S->L,n,TValue);
f->sizek=n;
+ for (i=0; i<n; i++) setnilvalue(&f->k[i]);
for (i=0; i<n; i++)
{
- TObject* o=&f->k[i];
- int t=LoadByte(S);
+ TValue* o=&f->k[i];
+ int t=LoadChar(S);
switch (t)
{
+ case LUA_TNIL:
+ setnilvalue(o);
+ break;
+ case LUA_TBOOLEAN:
+ setbvalue(o,LoadChar(S));
+ break;
case LUA_TNUMBER:
setnvalue(o,LoadNumber(S));
break;
case LUA_TSTRING:
- setsvalue2n(o,LoadString(S));
- break;
- case LUA_TNIL:
- setnilvalue(o);
+ setsvalue2n(S->L,o,LoadString(S));
break;
default:
- luaG_runerror(S->L,"bad constant type (%d) in %s",t,S->name);
+ IF (1, "bad constant");
break;
}
}
n=LoadInt(S);
f->p=luaM_newvector(S->L,n,Proto*);
f->sizep=n;
+ for (i=0; i<n; i++) f->p[i]=NULL;
for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source);
}
-static Proto* LoadFunction (LoadState* S, TString* p)
+static void LoadDebug(LoadState* S, Proto* f)
+{
+ int i,n;
+ n=LoadInt(S);
+ f->lineinfo=luaM_newvector(S->L,n,int);
+ f->sizelineinfo=n;
+ LoadVector(S,f->lineinfo,n,sizeof(int));
+ n=LoadInt(S);
+ f->locvars=luaM_newvector(S->L,n,LocVar);
+ f->sizelocvars=n;
+ for (i=0; i<n; i++) f->locvars[i].varname=NULL;
+ for (i=0; i<n; i++)
+ {
+ f->locvars[i].varname=LoadString(S);
+ f->locvars[i].startpc=LoadInt(S);
+ f->locvars[i].endpc=LoadInt(S);
+ }
+ n=LoadInt(S);
+ f->upvalues=luaM_newvector(S->L,n,TString*);
+ f->sizeupvalues=n;
+ for (i=0; i<n; i++) f->upvalues[i]=NULL;
+ for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);
+}
+
+static Proto* LoadFunction(LoadState* S, TString* p)
{
Proto* f=luaF_newproto(S->L);
+ setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
f->source=LoadString(S); if (f->source==NULL) f->source=p;
- f->lineDefined=LoadInt(S);
+ f->linedefined=LoadInt(S);
+ f->lastlinedefined=LoadInt(S);
f->nups=LoadByte(S);
f->numparams=LoadByte(S);
f->is_vararg=LoadByte(S);
f->maxstacksize=LoadByte(S);
- LoadLines(S,f);
- LoadLocals(S,f);
- LoadUpvalues(S,f);
- LoadConstants(S,f);
LoadCode(S,f);
-#ifndef TRUST_BINARIES
- if (!luaG_checkcode(f)) luaG_runerror(S->L,"bad code in %s",S->name);
-#endif
+ LoadConstants(S,f);
+ LoadDebug(S,f);
+ IF (!luaG_checkcode(f), "bad code");
+ S->L->top--;
return f;
}
-static void LoadSignature (LoadState* S)
-{
- const char* s=LUA_SIGNATURE;
- while (*s!=0 && ezgetc(S)==*s)
- ++s;
- if (*s!=0) luaG_runerror(S->L,"bad signature in %s",S->name);
-}
-
-static void TestSize (LoadState* S, int s, const char* what)
-{
- int r=LoadByte(S);
- if (r!=s)
- luaG_runerror(S->L,"virtual machine mismatch in %s: "
- "size of %s is %d but read %d",S->name,what,s,r);
-}
-
-#define TESTSIZE(s,w) TestSize(S,s,w)
-#define V(v) v/16,v%16
-
-static void LoadHeader (LoadState* S)
-{
- int version;
- lua_Number x,tx=TEST_NUMBER;
- LoadSignature(S);
- version=LoadByte(S);
- if (version>VERSION)
- luaG_runerror(S->L,"%s too new: "
- "read version %d.%d; expected at most %d.%d",
- S->name,V(version),V(VERSION));
- if (version<VERSION0) /* check last major change */
- luaG_runerror(S->L,"%s too old: "
- "read version %d.%d; expected at least %d.%d",
- S->name,V(version),V(VERSION0));
- S->swap=(luaU_endianness()!=LoadByte(S)); /* need to swap bytes? */
- TESTSIZE(sizeof(int),"int");
- TESTSIZE(sizeof(size_t), "size_t");
- TESTSIZE(sizeof(Instruction), "Instruction");
- TESTSIZE(SIZE_OP, "OP");
- TESTSIZE(SIZE_A, "A");
- TESTSIZE(SIZE_B, "B");
- TESTSIZE(SIZE_C, "C");
- TESTSIZE(sizeof(lua_Number), "number");
- x=LoadNumber(S);
- if ((long)x!=(long)tx) /* disregard errors in last bits of fraction */
- luaG_runerror(S->L,"unknown number format in %s",S->name);
-}
-
-static Proto* LoadChunk (LoadState* S)
+static void LoadHeader(LoadState* S)
{
- LoadHeader(S);
- return LoadFunction(S,NULL);
+ char h[LUAC_HEADERSIZE];
+ char s[LUAC_HEADERSIZE];
+ luaU_header(h);
+ LoadBlock(S,s,LUAC_HEADERSIZE);
+ IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header");
}
/*
** load precompiled chunk
*/
-Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff)
+Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
{
LoadState S;
- const char* s=zname(Z);
- if (*s=='@' || *s=='=')
- S.name=s+1;
- else if (*s==LUA_SIGNATURE[0])
+ if (*name=='@' || *name=='=')
+ S.name=name+1;
+ else if (*name==LUA_SIGNATURE[0])
S.name="binary string";
else
- S.name=s;
+ S.name=name;
S.L=L;
S.Z=Z;
S.b=buff;
- return LoadChunk(&S);
+ LoadHeader(&S);
+ return LoadFunction(&S,luaS_newliteral(L,"=?"));
}
/*
-** find byte order
+* make header
*/
-int luaU_endianness (void)
+void luaU_header (char* h)
{
int x=1;
- return *(char*)&x;
+ memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1);
+ h+=sizeof(LUA_SIGNATURE)-1;
+ *h++=(char)LUAC_VERSION;
+ *h++=(char)LUAC_FORMAT;
+ *h++=(char)*(char*)&x; /* endianness */
+ *h++=(char)sizeof(int);
+ *h++=(char)sizeof(size_t);
+ *h++=(char)sizeof(Instruction);
+ *h++=(char)sizeof(lua_Number);
+ *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */
}
diff --git a/lib/lua/src/lvm.c b/lib/lua/src/lvm.c
index 5103140..52f65e6 100644
--- a/lib/lua/src/lvm.c
+++ b/lib/lua/src/lvm.c
@@ -1,18 +1,16 @@
/*
-** $Id: lvm.c,v 1.10 2007-07-25 16:54:32 pixel Exp $
+** $Id: lvm.c,v 1.11 2007-07-27 10:05:54 pixel Exp $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
-#include <stdarg.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-/* needed only when `lua_number2str' uses `sprintf' */
-#include <stdio.h>
-
#define lvm_c
+#define LUA_CORE
#include "lua.h"
@@ -30,17 +28,11 @@
-/* function to convert a lua_Number to a string */
-#ifndef lua_number2str
-#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
-#endif
-
-
/* limit for table tag-method chains (to avoid loops) */
#define MAXTAGLOOP 100
-const TObject *luaV_tonumber (const TObject *obj, TObject *n) {
+const TValue *luaV_tonumber (const TValue *obj, TValue *n) {
lua_Number num;
if (ttisnumber(obj)) return obj;
if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {
@@ -53,149 +45,105 @@ const TObject *luaV_tonumber (const TObject *obj, TObject *n) {
int luaV_tostring (lua_State *L, StkId obj) {
-#if 0
if (!ttisnumber(obj))
return 0;
else {
- char s[32]; /* 16 digits, sign, point and \0 (+ some extra...) */
- lua_number2str(s, nvalue(obj));
- setsvalue2s(obj, luaS_new(L, s));
+ char s[LUAI_MAXNUMBER2STR];
+ lua_Number n = nvalue(obj);
+ lua_number2str(s, n);
+ setsvalue2s(L, obj, luaS_new(L, s));
return 1;
}
-#else
- if (ttisnumber(obj)) {
- char s[32]; /* 16 digits, sign, point and \0 (+ some extra...) */
- lua_number2str(s, nvalue(obj));
- setsvalue2s(obj, luaS_new(L, s));
- return 1;
- } else if (ttisboolean(obj)) {
- if (bvalue(obj))
- setsvalue2s(obj, luaS_new(L, "(true)"))
- else
- setsvalue2s(obj, luaS_new(L, "(false)"));
- return 1;
- } else if (ttisnil(obj)) {
- setsvalue(obj, luaS_new(L, "(nil)"));
- return 1;
- } else {
- return 0;
- }
-#endif
}
-static void traceexec (lua_State *L) {
+static void traceexec (lua_State *L, const Instruction *pc) {
lu_byte mask = L->hookmask;
- if (mask & LUA_MASKCOUNT) { /* instruction-hook set? */
+ const Instruction *oldpc = L->savedpc;
+ L->savedpc = pc;
+ if (mask > LUA_MASKLINE) { /* instruction-hook set? */
if (L->hookcount == 0) {
resethookcount(L);
luaD_callhook(L, LUA_HOOKCOUNT, -1);
- return;
}
}
if (mask & LUA_MASKLINE) {
- CallInfo *ci = L->ci;
- Proto *p = ci_func(ci)->l.p;
- int newline = getline(p, pcRel(*ci->u.l.pc, p));
- if (!L->hookinit) {
- luaG_inithooks(L);
- return;
- }
- lua_assert(ci->state & CI_HASFRAME);
- if (pcRel(*ci->u.l.pc, p) == 0) /* tracing may be starting now? */
- ci->u.l.savedpc = *ci->u.l.pc; /* initialize `savedpc' */
- /* calls linehook when enters a new line or jumps back (loop) */
- if (*ci->u.l.pc <= ci->u.l.savedpc ||
- newline != getline(p, pcRel(ci->u.l.savedpc, p))) {
+ Proto *p = ci_func(L->ci)->l.p;
+ int npc = pcRel(pc, p);
+ int newline = getline(p, npc);
+ /* call linehook when enter a new function, when jump back (loop),
+ or when enter a new line */
+ if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p)))
luaD_callhook(L, LUA_HOOKLINE, newline);
- ci = L->ci; /* previous call may reallocate `ci' */
- }
- ci->u.l.savedpc = *ci->u.l.pc;
}
}
-static void callTMres (lua_State *L, const TObject *f,
- const TObject *p1, const TObject *p2) {
- setobj2s(L->top, f); /* push function */
- setobj2s(L->top+1, p1); /* 1st argument */
- setobj2s(L->top+2, p2); /* 2nd argument */
- luaD_checkstack(L, 3); /* cannot check before (could invalidate p1, p2) */
+static void callTMres (lua_State *L, StkId res, const TValue *f,
+ const TValue *p1, const TValue *p2) {
+ ptrdiff_t result = savestack(L, res);
+ setobj2s(L, L->top, f); /* push function */
+ setobj2s(L, L->top+1, p1); /* 1st argument */
+ setobj2s(L, L->top+2, p2); /* 2nd argument */
+ luaD_checkstack(L, 3);
L->top += 3;
luaD_call(L, L->top - 3, 1);
- L->top--; /* result will be in L->top */
+ res = restorestack(L, result);
+ L->top--;
+ setobjs2s(L, res, L->top);
}
-static void callTM (lua_State *L, const TObject *f,
- const TObject *p1, const TObject *p2, const TObject *p3) {
- setobj2s(L->top, f); /* push function */
- setobj2s(L->top+1, p1); /* 1st argument */
- setobj2s(L->top+2, p2); /* 2nd argument */
- setobj2s(L->top+3, p3); /* 3th argument */
- luaD_checkstack(L, 4); /* cannot check before (could invalidate p1...p3) */
+static void callTM (lua_State *L, const TValue *f, const TValue *p1,
+ const TValue *p2, const TValue *p3) {
+ setobj2s(L, L->top, f); /* push function */
+ setobj2s(L, L->top+1, p1); /* 1st argument */
+ setobj2s(L, L->top+2, p2); /* 2nd argument */
+ setobj2s(L, L->top+3, p3); /* 3th argument */
+ luaD_checkstack(L, 4);
L->top += 4;
luaD_call(L, L->top - 4, 0);
}
-static const TObject *luaV_index (lua_State *L, const TObject *t,
- TObject *key, int loop) {
- const TObject *tm = fasttm(L, hvalue(t)->metatable, TM_INDEX);
- if (tm == NULL) return &luaO_nilobject; /* no TM */
- if (ttisfunction(tm)) {
- callTMres(L, tm, t, key);
- return L->top;
- }
- else return luaV_gettable(L, tm, key, loop);
-}
-
-static const TObject *luaV_getnotable (lua_State *L, const TObject *t,
- TObject *key, int loop) {
- const TObject *tm = luaT_gettmbyobj(L, t, TM_INDEX);
- if (ttisnil(tm))
- luaG_typeerror(L, t, "index");
- if (ttisfunction(tm)) {
- callTMres(L, tm, t, key);
- return L->top;
- }
- else return luaV_gettable(L, tm, key, loop);
-}
-
-
-/*
-** Function to index a table.
-** Receives the table at `t' and the key at `key'.
-** leaves the result at `res'.
-*/
-const TObject *luaV_gettable (lua_State *L, const TObject *t, TObject *key,
- int loop) {
- if (loop > MAXTAGLOOP)
- luaG_runerror(L, "loop in gettable");
- if (ttistable(t)) { /* `t' is a table? */
- Table *h = hvalue(t);
- const TObject *v = luaH_get(h, key); /* do a primitive get */
- if (!ttisnil(v)) return v;
- else return luaV_index(L, t, key, loop+1);
+void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
+ int loop;
+ for (loop = 0; loop < MAXTAGLOOP; loop++) {
+ const TValue *tm;
+ if (ttistable(t)) { /* `t' is a table? */
+ Table *h = hvalue(t);
+ const TValue *res = luaH_get(h, key); /* do a primitive get */
+ if (!ttisnil(res) || /* result is no nil? */
+ (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
+ setobj2s(L, val, res);
+ return;
+ }
+ /* else will try the tag method */
+ }
+ else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
+ luaG_typeerror(L, t, "index");
+ if (ttisfunction(tm)) {
+ callTMres(L, val, tm, t, key);
+ return;
+ }
+ t = tm; /* else repeat with `tm' */
}
- else return luaV_getnotable(L, t, key, loop+1);
+ luaG_runerror(L, "loop in gettable");
}
-/*
-** Receives table at `t', key at `key' and value at `val'.
-*/
-void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val) {
- const TObject *tm;
- int loop = 0;
- do {
+void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
+ int loop;
+ for (loop = 0; loop < MAXTAGLOOP; loop++) {
+ const TValue *tm;
if (ttistable(t)) { /* `t' is a table? */
Table *h = hvalue(t);
- TObject *oldval = luaH_set(L, h, key); /* do a primitive set */
+ TValue *oldval = luaH_set(L, h, key); /* do a primitive set */
if (!ttisnil(oldval) || /* result is no nil? */
(tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
- setobj2t(oldval, val); /* write barrier */
+ setobj2t(L, oldval, val);
+ luaC_barriert(L, h, val);
return;
}
/* else will try the tag method */
@@ -207,29 +155,26 @@ void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val) {
return;
}
t = tm; /* else repeat with `tm' */
- } while (++loop <= MAXTAGLOOP);
+ }
luaG_runerror(L, "loop in settable");
}
-static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2,
+static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2,
StkId res, TMS event) {
- ptrdiff_t result = savestack(L, res);
- const TObject *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
+ const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
if (ttisnil(tm))
tm = luaT_gettmbyobj(L, p2, event); /* try second operand */
- if (!ttisfunction(tm)) return 0;
- callTMres(L, tm, p1, p2);
- res = restorestack(L, result); /* previous call may change stack */
- setobjs2s(res, L->top);
+ if (ttisnil(tm)) return 0;
+ callTMres(L, res, tm, p1, p2);
return 1;
}
-static const TObject *get_compTM (lua_State *L, Table *mt1, Table *mt2,
+static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2,
TMS event) {
- const TObject *tm1 = fasttm(L, mt1, event);
- const TObject *tm2;
+ const TValue *tm1 = fasttm(L, mt1, event);
+ const TValue *tm2;
if (tm1 == NULL) return NULL; /* no metamethod */
if (mt1 == mt2) return tm1; /* same metatables => same metamethods */
tm2 = fasttm(L, mt2, event);
@@ -240,20 +185,20 @@ static const TObject *get_compTM (lua_State *L, Table *mt1, Table *mt2,
}
-static int call_orderTM (lua_State *L, const TObject *p1, const TObject *p2,
+static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2,
TMS event) {
- const TObject *tm1 = luaT_gettmbyobj(L, p1, event);
- const TObject *tm2;
+ const TValue *tm1 = luaT_gettmbyobj(L, p1, event);
+ const TValue *tm2;
if (ttisnil(tm1)) return -1; /* no metamethod? */
tm2 = luaT_gettmbyobj(L, p2, event);
if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */
return -1;
- callTMres(L, tm1, p1, p2);
+ callTMres(L, L->top, tm1, p1, p2);
return !l_isfalse(L->top);
}
-static int luaV_strcmp (const TString *ls, const TString *rs) {
+static int l_strcmp (const TString *ls, const TString *rs) {
const char *l = getstr(ls);
size_t ll = ls->tsv.len;
const char *r = getstr(rs);
@@ -275,28 +220,28 @@ static int luaV_strcmp (const TString *ls, const TString *rs) {
}
-int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) {
+int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
int res;
if (ttype(l) != ttype(r))
return luaG_ordererror(L, l, r);
else if (ttisnumber(l))
- return nvalue(l) < nvalue(r);
+ return luai_numlt(nvalue(l), nvalue(r));
else if (ttisstring(l))
- return luaV_strcmp(tsvalue(l), tsvalue(r)) < 0;
+ return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
return res;
return luaG_ordererror(L, l, r);
}
-static int luaV_lessequal (lua_State *L, const TObject *l, const TObject *r) {
+static int lessequal (lua_State *L, const TValue *l, const TValue *r) {
int res;
if (ttype(l) != ttype(r))
return luaG_ordererror(L, l, r);
else if (ttisnumber(l))
- return nvalue(l) <= nvalue(r);
+ return luai_numle(nvalue(l), nvalue(r));
else if (ttisstring(l))
- return luaV_strcmp(tsvalue(l), tsvalue(r)) <= 0;
+ return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */
return res;
else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */
@@ -305,17 +250,17 @@ static int luaV_lessequal (lua_State *L, const TObject *l, const TObject *r) {
}
-int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2) {
- const TObject *tm;
+int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {
+ const TValue *tm;
lua_assert(ttype(t1) == ttype(t2));
switch (ttype(t1)) {
case LUA_TNIL: return 1;
- case LUA_TNUMBER: return nvalue(t1) == nvalue(t2);
+ case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));
case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */
case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
case LUA_TUSERDATA: {
if (uvalue(t1) == uvalue(t2)) return 1;
- tm = get_compTM(L, uvalue(t1)->uv.metatable, uvalue(t2)->uv.metatable,
+ tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable,
TM_EQ);
break; /* will try TM */
}
@@ -327,7 +272,7 @@ int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2) {
default: return gcvalue(t1) == gcvalue(t2);
}
if (tm == NULL) return 0; /* no TM? */
- callTMres(L, tm, t1, t2); /* call TM */
+ callTMres(L, L->top, tm, t1, t2); /* call TM */
return !l_isfalse(L->top);
}
@@ -336,28 +281,30 @@ void luaV_concat (lua_State *L, int total, int last) {
do {
StkId top = L->base + last + 1;
int n = 2; /* number of elements handled in this pass (at least 2) */
- if (!tostring(L, top-2) || !tostring(L, top-1)) {
+ if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {
if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
luaG_concaterror(L, top-2, top-1);
- } else if (tsvalue(top-1)->tsv.len > 0) { /* if len=0, do nothing */
+ } else if (tsvalue(top-1)->len == 0) /* second op is empty? */
+ (void)tostring(L, top - 2); /* result is first op (as string) */
+ else {
/* at least two string values; get as many as possible */
- size_t tl = tsvalue(top-1)->tsv.len;
+ size_t tl = tsvalue(top-1)->len;
char *buffer;
int i;
/* collect total length */
for (n = 1; n < total && tostring(L, top-n-1); n++) {
- size_t l = tsvalue(top-n-1)->tsv.len;
+ size_t l = tsvalue(top-n-1)->len;
if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow");
tl += l;
}
buffer = luaZ_openspace(L, &G(L)->buff, tl);
tl = 0;
for (i=n; i>0; i--) { /* concat all strings */
- size_t l = tsvalue(top-i)->tsv.len;
+ size_t l = tsvalue(top-i)->len;
memcpy(buffer+tl, svalue(top-i), l);
tl += l;
}
- setsvalue2s(top-n, luaS_newlstr(L, buffer, tl));
+ setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));
}
total -= n-1; /* got `n' strings to create 1 new */
last -= n-1;
@@ -365,27 +312,21 @@ void luaV_concat (lua_State *L, int total, int last) {
}
-static void Arith (lua_State *L, StkId ra,
- const TObject *rb, const TObject *rc, TMS op) {
- TObject tempb, tempc;
- const TObject *b, *c;
+static void Arith (lua_State *L, StkId ra, const TValue *rb,
+ const TValue *rc, TMS op) {
+ TValue tempb, tempc;
+ const TValue *b, *c;
if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
(c = luaV_tonumber(rc, &tempc)) != NULL) {
+ lua_Number nb = nvalue(b), nc = nvalue(c);
switch (op) {
- case TM_ADD: setnvalue(ra, nvalue(b) + nvalue(c)); break;
- case TM_SUB: setnvalue(ra, nvalue(b) - nvalue(c)); break;
- case TM_MUL: setnvalue(ra, nvalue(b) * nvalue(c)); break;
- case TM_DIV: setnvalue(ra, nvalue(b) / nvalue(c)); break;
- case TM_POW: {
- const TObject *f = luaH_getstr(hvalue(gt(L)), G(L)->tmname[TM_POW]);
- ptrdiff_t res = savestack(L, ra);
- if (!ttisfunction(f))
- luaG_runerror(L, "`__pow' (`^' operator) is not a function");
- callTMres(L, f, b, c);
- ra = restorestack(L, res); /* previous call may change stack */
- setobjs2s(ra, L->top);
- break;
- }
+ case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break;
+ case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break;
+ case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break;
+ case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break;
+ case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break;
+ case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break;
+ case TM_UNM: setnvalue(ra, luai_numunm(nb)); break;
default: lua_assert(0); break;
}
}
@@ -399,384 +340,387 @@ static void Arith (lua_State *L, StkId ra,
** some macros for common tasks in `luaV_execute'
*/
-#define runtime_check(L, c) { if (!(c)) return 0; }
+#define runtime_check(L, c) { if (!(c)) break; }
#define RA(i) (base+GETARG_A(i))
/* to be used after possible stack reallocation */
-#define XRA(i) (L->base+GETARG_A(i))
-#define RB(i) (base+GETARG_B(i))
-#define RKB(i) ((GETARG_B(i) < MAXSTACK) ? RB(i) : k+GETARG_B(i)-MAXSTACK)
-#define RC(i) (base+GETARG_C(i))
-#define RKC(i) ((GETARG_C(i) < MAXSTACK) ? RC(i) : k+GETARG_C(i)-MAXSTACK)
-#define KBx(i) (k+GETARG_Bx(i))
+#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i))
+#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))
+#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \
+ ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i))
+#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \
+ ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i))
+#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i))
+
+
+#define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);}
-#define dojump(pc, i) ((pc) += (i))
+#define Protect(x) { L->savedpc = pc; {x;}; base = L->base; }
-StkId luaV_execute (lua_State *L) {
+#define arith_op(op,tm) { \
+ TValue *rb = RKB(i); \
+ TValue *rc = RKC(i); \
+ if (ttisnumber(rb) && ttisnumber(rc)) { \
+ lua_Number nb = nvalue(rb), nc = nvalue(rc); \
+ setnvalue(ra, op(nb, nc)); \
+ } \
+ else \
+ Protect(Arith(L, ra, rb, rc, tm)); \
+ }
+
+
+
+void luaV_execute (lua_State *L, int nexeccalls) {
LClosure *cl;
- TObject *k;
+ StkId base;
+ TValue *k;
const Instruction *pc;
- callentry: /* entry point when calling new functions */
- if (L->hookmask & LUA_MASKCALL) {
- L->ci->u.l.pc = &pc;
- luaD_callhook(L, LUA_HOOKCALL, -1);
- }
- retentry: /* entry point when returning to old functions */
- L->ci->u.l.pc = &pc;
- lua_assert(L->ci->state == CI_SAVEDPC ||
- L->ci->state == (CI_SAVEDPC | CI_CALLING));
- L->ci->state = CI_HASFRAME; /* activate frame */
- pc = L->ci->u.l.savedpc;
- cl = &clvalue(L->base - 1)->l;
+ reentry: /* entry point */
+ lua_assert(isLua(L->ci));
+ pc = L->savedpc;
+ cl = &clvalue(L->ci->func)->l;
+ base = L->base;
k = cl->p->k;
/* main loop of interpreter */
for (;;) {
const Instruction i = *pc++;
- StkId base, ra;
+ StkId ra;
if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
- traceexec(L);
- if (L->ci->state & CI_YIELD) { /* did hook yield? */
- L->ci->u.l.savedpc = pc - 1;
- L->ci->state = CI_YIELD | CI_SAVEDPC;
- return NULL;
- }
- if (L->ci->state & CI_BREAK) { /* did hook break? */
- L->ci->state &= ~CI_BREAK;
- luaG_runerror(L, "breaking");
+ traceexec(L, pc);
+ if (L->status == LUA_YIELD) { /* did hook yield? */
+ L->savedpc = pc - 1;
+ return;
}
+ base = L->base;
+ }
+ if (L->do_break) {
+ L->do_break = 0;
+ luaG_runerror(L, "breaking");
}
/* warning!! several calls may realloc the stack and invalidate `ra' */
- base = L->base;
ra = RA(i);
- lua_assert(L->ci->state & CI_HASFRAME);
- lua_assert(base == L->ci->base);
- lua_assert(L->top <= L->stack + L->stacksize && L->top >= base);
- lua_assert(L->top == L->ci->top ||
- GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL ||
- GET_OPCODE(i) == OP_RETURN || GET_OPCODE(i) == OP_SETLISTO);
+ lua_assert(base == L->base && L->base == L->ci->base);
+ lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);
+ lua_assert(L->top == L->ci->top || luaG_checkopenop(i));
switch (GET_OPCODE(i)) {
case OP_MOVE: {
- setobjs2s(ra, RB(i));
- break;
+ setobjs2s(L, ra, RB(i));
+ continue;
}
case OP_LOADK: {
- setobj2s(ra, KBx(i));
- break;
+ setobj2s(L, ra, KBx(i));
+ continue;
}
case OP_LOADBOOL: {
setbvalue(ra, GETARG_B(i));
if (GETARG_C(i)) pc++; /* skip next instruction (if C) */
- break;
+ continue;
}
case OP_LOADNIL: {
- TObject *rb = RB(i);
+ TValue *rb = RB(i);
do {
setnilvalue(rb--);
} while (rb >= ra);
- break;
+ continue;
}
case OP_GETUPVAL: {
int b = GETARG_B(i);
- setobj2s(ra, cl->upvals[b]->v);
- break;
+ setobj2s(L, ra, cl->upvals[b]->v);
+ continue;
}
case OP_GETGLOBAL: {
- TObject *rb = KBx(i);
- const TObject *v;
- lua_assert(ttisstring(rb) && ttistable(&cl->g));
- v = luaH_getstr(hvalue(&cl->g), tsvalue(rb));
- if (!ttisnil(v)) { setobj2s(ra, v); }
- else
- setobj2s(XRA(i), luaV_index(L, &cl->g, rb, 0));
- break;
+ TValue g;
+ TValue *rb = KBx(i);
+ sethvalue(L, &g, cl->env);
+ lua_assert(ttisstring(rb));
+ Protect(luaV_gettable(L, &g, rb, ra));
+ continue;
}
case OP_GETTABLE: {
- StkId rb = RB(i);
- TObject *rc = RKC(i);
- if (ttistable(rb)) {
- const TObject *v = luaH_get(hvalue(rb), rc);
- if (!ttisnil(v)) { setobj2s(ra, v); }
- else
- setobj2s(XRA(i), luaV_index(L, rb, rc, 0));
- }
- else
- setobj2s(XRA(i), luaV_getnotable(L, rb, rc, 0));
- break;
+ Protect(luaV_gettable(L, RB(i), RKC(i), ra));
+ continue;
}
case OP_SETGLOBAL: {
- lua_assert(ttisstring(KBx(i)) && ttistable(&cl->g));
- luaV_settable(L, &cl->g, KBx(i), ra);
- break;
+ TValue g;
+ sethvalue(L, &g, cl->env);
+ lua_assert(ttisstring(KBx(i)));
+ Protect(luaV_settable(L, &g, KBx(i), ra));
+ continue;
}
case OP_SETUPVAL: {
- int b = GETARG_B(i);
- setobj(cl->upvals[b]->v, ra); /* write barrier */
- break;
+ UpVal *uv = cl->upvals[GETARG_B(i)];
+ setobj(L, uv->v, ra);
+ luaC_barrier(L, uv, ra);
+ continue;
}
case OP_SETTABLE: {
- luaV_settable(L, ra, RKB(i), RKC(i));
- break;
+ Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
+ continue;
}
case OP_NEWTABLE: {
int b = GETARG_B(i);
- b = fb2int(b);
- sethvalue(ra, luaH_new(L, b, GETARG_C(i)));
- luaC_checkGC(L);
- break;
+ int c = GETARG_C(i);
+ sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));
+ Protect(luaC_checkGC(L));
+ continue;
}
case OP_SELF: {
StkId rb = RB(i);
- TObject *rc = RKC(i);
- runtime_check(L, ttisstring(rc));
- setobjs2s(ra+1, rb);
- if (ttistable(rb)) {
- const TObject *v = luaH_getstr(hvalue(rb), tsvalue(rc));
- if (!ttisnil(v)) { setobj2s(ra, v); }
- else
- setobj2s(XRA(i), luaV_index(L, rb, rc, 0));
- }
- else
- setobj2s(XRA(i), luaV_getnotable(L, rb, rc, 0));
- break;
+ setobjs2s(L, ra+1, rb);
+ Protect(luaV_gettable(L, rb, RKC(i), ra));
+ continue;
}
case OP_ADD: {
- TObject *rb = RKB(i);
- TObject *rc = RKC(i);
- if (ttisnumber(rb) && ttisnumber(rc)) {
- setnvalue(ra, nvalue(rb) + nvalue(rc));
- }
- else
- Arith(L, ra, rb, rc, TM_ADD);
- break;
+ arith_op(luai_numadd, TM_ADD);
+ continue;
}
case OP_SUB: {
- TObject *rb = RKB(i);
- TObject *rc = RKC(i);
- if (ttisnumber(rb) && ttisnumber(rc)) {
- setnvalue(ra, nvalue(rb) - nvalue(rc));
- }
- else
- Arith(L, ra, rb, rc, TM_SUB);
- break;
+ arith_op(luai_numsub, TM_SUB);
+ continue;
}
case OP_MUL: {
- TObject *rb = RKB(i);
- TObject *rc = RKC(i);
- if (ttisnumber(rb) && ttisnumber(rc)) {
- setnvalue(ra, nvalue(rb) * nvalue(rc));
- }
- else
- Arith(L, ra, rb, rc, TM_MUL);
- break;
+ arith_op(luai_nummul, TM_MUL);
+ continue;
}
case OP_DIV: {
- TObject *rb = RKB(i);
- TObject *rc = RKC(i);
- if (ttisnumber(rb) && ttisnumber(rc)) {
- setnvalue(ra, nvalue(rb) / nvalue(rc));
- }
- else
- Arith(L, ra, rb, rc, TM_DIV);
- break;
+ arith_op(luai_numdiv, TM_DIV);
+ continue;
+ }
+ case OP_MOD: {
+ arith_op(luai_nummod, TM_MOD);
+ continue;
}
case OP_POW: {
- Arith(L, ra, RKB(i), RKC(i), TM_POW);
- break;
+ arith_op(luai_numpow, TM_POW);
+ continue;
}
case OP_UNM: {
- const TObject *rb = RB(i);
- TObject temp;
- if (tonumber(rb, &temp)) {
- setnvalue(ra, -nvalue(rb));
+ TValue *rb = RB(i);
+ if (ttisnumber(rb)) {
+ lua_Number nb = nvalue(rb);
+ setnvalue(ra, luai_numunm(nb));
}
else {
- setnilvalue(&temp);
- if (!call_binTM(L, RB(i), &temp, ra, TM_UNM))
- luaG_aritherror(L, RB(i), &temp);
+ Protect(Arith(L, ra, rb, rb, TM_UNM));
}
- break;
+ continue;
}
case OP_NOT: {
int res = l_isfalse(RB(i)); /* next assignment may change this value */
setbvalue(ra, res);
- break;
+ continue;
+ }
+ case OP_LEN: {
+ const TValue *rb = RB(i);
+ switch (ttype(rb)) {
+ case LUA_TTABLE: {
+ setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));
+ break;
+ }
+ case LUA_TSTRING: {
+ setnvalue(ra, cast_num(tsvalue(rb)->len));
+ break;
+ }
+ default: { /* try metamethod */
+ Protect(
+ if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN))
+ luaG_typeerror(L, rb, "get length of");
+ )
+ }
+ }
+ continue;
}
case OP_CONCAT: {
int b = GETARG_B(i);
int c = GETARG_C(i);
- luaV_concat(L, c-b+1, c); /* may change `base' (and `ra') */
- base = L->base;
- setobjs2s(RA(i), base+b);
- luaC_checkGC(L);
- break;
+ Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L));
+ setobjs2s(L, RA(i), base+b);
+ continue;
}
case OP_JMP: {
- dojump(pc, GETARG_sBx(i));
- break;
+ dojump(L, pc, GETARG_sBx(i));
+ continue;
}
case OP_EQ: {
- if (equalobj(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++;
- else dojump(pc, GETARG_sBx(*pc) + 1);
- break;
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
+ Protect(
+ if (equalobj(L, rb, rc) == GETARG_A(i))
+ dojump(L, pc, GETARG_sBx(*pc));
+ )
+ pc++;
+ continue;
}
case OP_LT: {
- if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++;
- else dojump(pc, GETARG_sBx(*pc) + 1);
- break;
+ Protect(
+ if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i))
+ dojump(L, pc, GETARG_sBx(*pc));
+ )
+ pc++;
+ continue;
}
case OP_LE: {
- if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++;
- else dojump(pc, GETARG_sBx(*pc) + 1);
- break;
+ Protect(
+ if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))
+ dojump(L, pc, GETARG_sBx(*pc));
+ )
+ pc++;
+ continue;
}
case OP_TEST: {
- TObject *rb = RB(i);
- if (l_isfalse(rb) == GETARG_C(i)) pc++;
- else {
- setobjs2s(ra, rb);
- dojump(pc, GETARG_sBx(*pc) + 1);
+ if (l_isfalse(ra) != GETARG_C(i))
+ dojump(L, pc, GETARG_sBx(*pc));
+ pc++;
+ continue;
+ }
+ case OP_TESTSET: {
+ TValue *rb = RB(i);
+ if (l_isfalse(rb) != GETARG_C(i)) {
+ setobjs2s(L, ra, rb);
+ dojump(L, pc, GETARG_sBx(*pc));
}
- break;
+ pc++;
+ continue;
}
- case OP_CALL:
- case OP_TAILCALL: {
- StkId firstResult;
+ case OP_CALL: {
int b = GETARG_B(i);
- int nresults;
+ int nresults = GETARG_C(i) - 1;
if (b != 0) L->top = ra+b; /* else previous instruction set top */
- nresults = GETARG_C(i) - 1;
- firstResult = luaD_precall(L, ra);
- if (firstResult) {
- if (firstResult > L->top) { /* yield? */
- lua_assert(L->ci->state == (CI_C | CI_YIELD));
- (L->ci - 1)->u.l.savedpc = pc;
- (L->ci - 1)->state = CI_SAVEDPC;
- return NULL;
+ L->savedpc = pc;
+ switch (luaD_precall(L, ra, nresults)) {
+ case PCRLUA: {
+ nexeccalls++;
+ goto reentry; /* restart luaV_execute over new Lua function */
}
- /* it was a C function (`precall' called it); adjust results */
- luaD_poscall(L, nresults, firstResult);
- if (nresults >= 0) L->top = L->ci->top;
- }
- else { /* it is a Lua function */
- if (GET_OPCODE(i) == OP_CALL) { /* regular call? */
- (L->ci-1)->u.l.savedpc = pc; /* save `pc' to return later */
- (L->ci-1)->state = (CI_SAVEDPC | CI_CALLING);
+ case PCRC: {
+ /* it was a C function (`precall' called it); adjust results */
+ if (nresults >= 0) L->top = L->ci->top;
+ base = L->base;
+ continue;
}
- else { /* tail call: put new frame in place of previous one */
+ default: {
+ return; /* yield */
+ }
+ }
+ }
+ case OP_TAILCALL: {
+ int b = GETARG_B(i);
+ if (b != 0) L->top = ra+b; /* else previous instruction set top */
+ L->savedpc = pc;
+ lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
+ switch (luaD_precall(L, ra, LUA_MULTRET)) {
+ case PCRLUA: {
+ /* tail call: put new frame in place of previous one */
+ CallInfo *ci = L->ci - 1; /* previous frame */
int aux;
- base = (L->ci - 1)->base; /* `luaD_precall' may change the stack */
- ra = RA(i);
- if (L->openupval) luaF_close(L, base);
- for (aux = 0; ra+aux < L->top; aux++) /* move frame down */
- setobjs2s(base+aux-1, ra+aux);
- (L->ci - 1)->top = L->top = base+aux; /* correct top */
- lua_assert(L->ci->state & CI_SAVEDPC);
- (L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc;
- (L->ci - 1)->u.l.tailcalls++; /* one more call lost */
- (L->ci - 1)->state = CI_SAVEDPC;
+ StkId func = ci->func;
+ StkId pfunc = (ci+1)->func; /* previous function index */
+ if (L->openupval) luaF_close(L, ci->base);
+ L->base = ci->base = ci->func + ((ci+1)->base - pfunc);
+ for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */
+ setobjs2s(L, func+aux, pfunc+aux);
+ ci->top = L->top = func+aux; /* correct top */
+ lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize);
+ ci->savedpc = L->savedpc;
+ ci->tailcalls++; /* one more call lost */
L->ci--; /* remove new frame */
- L->base = L->ci->base;
+ goto reentry;
+ }
+ case PCRC: { /* it was a C function (`precall' called it) */
+ base = L->base;
+ continue;
+ }
+ default: {
+ return; /* yield */
}
- goto callentry;
}
- break;
}
case OP_RETURN: {
- CallInfo *ci = L->ci - 1; /* previous function frame */
int b = GETARG_B(i);
if (b != 0) L->top = ra+b-1;
- lua_assert(L->ci->state & CI_HASFRAME);
if (L->openupval) luaF_close(L, base);
- L->ci->state = CI_SAVEDPC; /* deactivate current function */
- L->ci->u.l.savedpc = pc;
- /* previous function was running `here'? */
- if (!(ci->state & CI_CALLING)) {
- lua_assert((ci->state & CI_C) || ci->u.l.pc != &pc);
- return ra; /* no: return */
- }
+ L->savedpc = pc;
+ b = luaD_poscall(L, ra);
+ if (--nexeccalls == 0) /* was previous function running `here'? */
+ return; /* no: return */
else { /* yes: continue its execution */
- int nresults;
- lua_assert(ttisfunction(ci->base - 1) && (ci->state & CI_SAVEDPC));
- lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL);
- nresults = GETARG_C(*(ci->u.l.savedpc - 1)) - 1;
- luaD_poscall(L, nresults, ra);
- if (nresults >= 0) L->top = L->ci->top;
- goto retentry;
+ if (b) L->top = L->ci->top;
+ lua_assert(isLua(L->ci));
+ lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL);
+ goto reentry;
}
}
case OP_FORLOOP: {
- lua_Number step, idx, limit;
- const TObject *plimit = ra+1;
- const TObject *pstep = ra+2;
- if (!ttisnumber(ra))
- luaG_runerror(L, "`for' initial value must be a number");
- if (!tonumber(plimit, ra+1))
- luaG_runerror(L, "`for' limit must be a number");
- if (!tonumber(pstep, ra+2))
- luaG_runerror(L, "`for' step must be a number");
- step = nvalue(pstep);
- idx = nvalue(ra) + step; /* increment index */
- limit = nvalue(plimit);
- if (step > 0 ? idx <= limit : idx >= limit) {
- dojump(pc, GETARG_sBx(i)); /* jump back */
- chgnvalue(ra, idx); /* update index */
+ lua_Number step = nvalue(ra+2);
+ lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */
+ lua_Number limit = nvalue(ra+1);
+ if (luai_numlt(0, step) ? luai_numle(idx, limit)
+ : luai_numle(limit, idx)) {
+ dojump(L, pc, GETARG_sBx(i)); /* jump back */
+ setnvalue(ra, idx); /* update internal index... */
+ setnvalue(ra+3, idx); /* ...and external index */
}
- break;
+ continue;
+ }
+ case OP_FORPREP: {
+ const TValue *init = ra;
+ const TValue *plimit = ra+1;
+ const TValue *pstep = ra+2;
+ L->savedpc = pc; /* next steps may throw errors */
+ if (!tonumber(init, ra))
+ luaG_runerror(L, LUA_QL("for") " initial value must be a number");
+ else if (!tonumber(plimit, ra+1))
+ luaG_runerror(L, LUA_QL("for") " limit must be a number");
+ else if (!tonumber(pstep, ra+2))
+ luaG_runerror(L, LUA_QL("for") " step must be a number");
+ setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));
+ dojump(L, pc, GETARG_sBx(i));
+ continue;
}
case OP_TFORLOOP: {
- int nvar = GETARG_C(i) + 1;
- StkId cb = ra + nvar + 2; /* call base */
- setobjs2s(cb, ra);
- setobjs2s(cb+1, ra+1);
- setobjs2s(cb+2, ra+2);
+ StkId cb = ra + 3; /* call base */
+ setobjs2s(L, cb+2, ra+2);
+ setobjs2s(L, cb+1, ra+1);
+ setobjs2s(L, cb, ra);
L->top = cb+3; /* func. + 2 args (state and index) */
- luaD_call(L, cb, nvar);
+ Protect(luaD_call(L, cb, GETARG_C(i)));
L->top = L->ci->top;
- ra = XRA(i) + 2; /* final position of first result */
- cb = ra + nvar;
- do { /* move results to proper positions */
- nvar--;
- setobjs2s(ra+nvar, cb+nvar);
- } while (nvar > 0);
- if (ttisnil(ra)) /* break loop? */
- pc++; /* skip jump (break loop) */
- else
- dojump(pc, GETARG_sBx(*pc) + 1); /* jump back */
- break;
- }
- case OP_TFORPREP: { /* for compatibility only */
- if (ttistable(ra)) {
- setobjs2s(ra+1, ra);
- setobj2s(ra, luaH_getstr(hvalue(gt(L)), luaS_new(L, "next")));
+ cb = RA(i) + 3; /* previous call may change the stack */
+ if (!ttisnil(cb)) { /* continue loop? */
+ setobjs2s(L, cb-1, cb); /* save control variable */
+ dojump(L, pc, GETARG_sBx(*pc)); /* jump back */
}
- dojump(pc, GETARG_sBx(i));
- break;
+ pc++;
+ continue;
}
- case OP_SETLIST:
- case OP_SETLISTO: {
- int bc;
- int n;
+ case OP_SETLIST: {
+ int n = GETARG_B(i);
+ int c = GETARG_C(i);
+ int last;
Table *h;
+ if (n == 0) {
+ n = cast_int(L->top - ra) - 1;
+ L->top = L->ci->top;
+ }
+ if (c == 0) c = cast_int(*pc++);
runtime_check(L, ttistable(ra));
h = hvalue(ra);
- bc = GETARG_Bx(i);
- if (GET_OPCODE(i) == OP_SETLIST)
- n = (bc&(LFIELDS_PER_FLUSH-1)) + 1;
- else {
- n = L->top - ra - 1;
- L->top = L->ci->top;
+ last = ((c-1)*LFIELDS_PER_FLUSH) + n;
+ if (last > h->sizearray) /* needs more space? */
+ luaH_resizearray(L, h, last); /* pre-alloc it at once */
+ for (; n > 0; n--) {
+ TValue *val = ra+n;
+ setobj2t(L, luaH_setnum(L, h, last--), val);
+ luaC_barriert(L, h, val);
}
- bc &= ~(LFIELDS_PER_FLUSH-1); /* bc = bc - bc%FPF */
- for (; n > 0; n--)
- setobj2t(luaH_setnum(L, h, bc+n), ra+n); /* write barrier */
- break;
+ continue;
}
case OP_CLOSE: {
luaF_close(L, ra);
- break;
+ continue;
}
case OP_CLOSURE: {
Proto *p;
@@ -784,7 +728,7 @@ StkId luaV_execute (lua_State *L) {
int nup, j;
p = cl->p->p[GETARG_Bx(i)];
nup = p->nups;
- ncl = luaF_newLclosure(L, nup, &cl->g);
+ ncl = luaF_newLclosure(L, nup, cl->env);
ncl->l.p = p;
for (j=0; j<nup; j++, pc++) {
if (GET_OPCODE(*pc) == OP_GETUPVAL)
@@ -794,9 +738,30 @@ StkId luaV_execute (lua_State *L) {
ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc));
}
}
- setclvalue(ra, ncl);
- luaC_checkGC(L);
- break;
+ setclvalue(L, ra, ncl);
+ Protect(luaC_checkGC(L));
+ continue;
+ }
+ case OP_VARARG: {
+ int b = GETARG_B(i) - 1;
+ int j;
+ CallInfo *ci = L->ci;
+ int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1;
+ if (b == LUA_MULTRET) {
+ Protect(luaD_checkstack(L, n));
+ ra = RA(i); /* previous call may change the stack */
+ b = n;
+ L->top = ra + n;
+ }
+ for (j = 0; j < b; j++) {
+ if (j < n) {
+ setobjs2s(L, ra + j, ci->base - n + j);
+ }
+ else {
+ setnilvalue(ra + j);
+ }
+ }
+ continue;
}
}
}
diff --git a/lib/lua/src/lzio.c b/lib/lua/src/lzio.c
index 277a656..8665a43 100644
--- a/lib/lua/src/lzio.c
+++ b/lib/lua/src/lzio.c
@@ -1,5 +1,5 @@
/*
-** $Id: lzio.c,v 1.4 2004-11-27 21:46:07 pixel Exp $
+** $Id: lzio.c,v 1.5 2007-07-27 10:05:54 pixel Exp $
** a generic input stream interface
** See Copyright Notice in lua.h
*/
@@ -8,17 +8,23 @@
#include <string.h>
#define lzio_c
+#define LUA_CORE
#include "lua.h"
#include "llimits.h"
#include "lmem.h"
+#include "lstate.h"
#include "lzio.h"
int luaZ_fill (ZIO *z) {
size_t size;
- const char *buff = z->reader(NULL, z->data, &size);
+ lua_State *L = z->L;
+ const char *buff;
+ lua_unlock(L);
+ buff = z->reader(L, z->data, &size);
+ lua_lock(L);
if (buff == NULL || size == 0) return EOZ;
z->n = size - 1;
z->p = buff;
@@ -28,19 +34,21 @@ int luaZ_fill (ZIO *z) {
int luaZ_lookahead (ZIO *z) {
if (z->n == 0) {
- int c = luaZ_fill(z);
- if (c == EOZ) return c;
- z->n++;
- z->p--;
+ if (luaZ_fill(z) == EOZ)
+ return EOZ;
+ else {
+ z->n++; /* luaZ_fill removed first byte; put back it */
+ z->p--;
+ }
}
return char2int(*z->p);
}
-void luaZ_init (ZIO *z, lua_Chunkreader reader, void *data, const char *name) {
+void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) {
+ z->L = L;
z->reader = reader;
z->data = data;
- z->name = name;
z->n = 0;
z->p = NULL;
}
@@ -50,14 +58,8 @@ void luaZ_init (ZIO *z, lua_Chunkreader reader, void *data, const char *name) {
size_t luaZ_read (ZIO *z, void *b, size_t n) {
while (n) {
size_t m;
- if (z->n == 0) {
- if (luaZ_fill(z) == EOZ)
- return n; /* return number of missing bytes */
- else {
- ++z->n; /* filbuf removed first byte; put back it */
- --z->p;
- }
- }
+ if (luaZ_lookahead(z) == EOZ)
+ return n; /* return number of missing bytes */
m = (n <= z->n) ? n : z->n; /* min. between n and z->n */
memcpy(b, z->p, m);
z->n -= m;
@@ -72,8 +74,7 @@ size_t luaZ_read (ZIO *z, void *b, size_t n) {
char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) {
if (n > buff->buffsize) {
if (n < LUA_MINBUFFER) n = LUA_MINBUFFER;
- luaM_reallocvector(L, buff->buffer, buff->buffsize, n, char);
- buff->buffsize = n;
+ luaZ_resizebuffer(L, buff, n);
}
return buff->buffer;
}