]> git.lizzy.rs Git - metalua.git/commitdiff
Towards 0.4.1: lua-5.1.3, pluto-2.2, 64 bits compatible dumper...
authorFabien Fleutot <fabien@macfabien.local>
Thu, 14 Feb 2008 08:53:59 +0000 (09:53 +0100)
committerFabien Fleutot <fabien@macfabien.local>
Thu, 14 Feb 2008 08:53:59 +0000 (09:53 +0100)
79 files changed:
src/binlibs/Makefile
src/binlibs/pluto.c [deleted file]
src/binlibs/pluto.h [deleted file]
src/binlibs/pluto/lzio.c [new file with mode: 0644]
src/binlibs/pluto/pdep.c [new file with mode: 0644]
src/binlibs/pluto/pdep/README [new file with mode: 0644]
src/binlibs/pluto/pdep/lauxlib.h [new file with mode: 0644]
src/binlibs/pluto/pdep/ldo.h [new file with mode: 0644]
src/binlibs/pluto/pdep/lfunc.h [new file with mode: 0644]
src/binlibs/pluto/pdep/lgc.h [new file with mode: 0644]
src/binlibs/pluto/pdep/llimits.h [new file with mode: 0644]
src/binlibs/pluto/pdep/lobject.h [new file with mode: 0644]
src/binlibs/pluto/pdep/lopcodes.h [new file with mode: 0644]
src/binlibs/pluto/pdep/lstate.h [new file with mode: 0644]
src/binlibs/pluto/pdep/lstring.h [new file with mode: 0644]
src/binlibs/pluto/pdep/ltm.h [new file with mode: 0644]
src/binlibs/pluto/pdep/lua.h [new file with mode: 0644]
src/binlibs/pluto/pdep/lzio.h [new file with mode: 0644]
src/binlibs/pluto/pdep/pdep.h [new file with mode: 0644]
src/binlibs/pluto/pluto.c [new file with mode: 0644]
src/binlibs/pluto/pluto.h [new file with mode: 0644]
src/compiler/Makefile
src/compiler/ldump.lua
src/config
src/lua/Makefile
src/lua/lapi.c
src/lua/lapi.h
src/lua/lauxlib.c
src/lua/lauxlib.h
src/lua/lbaselib.c
src/lua/lcode.c
src/lua/lcode.h
src/lua/ldblib.c
src/lua/ldebug.c
src/lua/ldebug.h
src/lua/ldo.c
src/lua/ldo.h
src/lua/ldump.c
src/lua/lfunc.c
src/lua/lfunc.h
src/lua/lgc.c
src/lua/lgc.h
src/lua/linit.c
src/lua/liolib.c
src/lua/llex.c
src/lua/llex.h
src/lua/llimits.h
src/lua/lmathlib.c
src/lua/lmem.c
src/lua/lmem.h
src/lua/loadlib.c
src/lua/lobject.c
src/lua/lobject.h
src/lua/lopcodes.c
src/lua/lopcodes.h
src/lua/loslib.c
src/lua/lparser.c
src/lua/lparser.h
src/lua/lstate.c
src/lua/lstate.h
src/lua/lstring.c
src/lua/lstring.h
src/lua/lstrlib.c
src/lua/ltable.c
src/lua/ltable.h
src/lua/ltablib.c
src/lua/ltm.c
src/lua/ltm.h
src/lua/lua.c
src/lua/lua.h
src/lua/luaconf.h
src/lua/lualib.h
src/lua/lundump.c
src/lua/lundump.h
src/lua/lvm.c
src/lua/lvm.h
src/lua/lzio.c
src/lua/lzio.h
src/win32/make-win32-msvc.bat

index 1c0da6d79ec081e7ea96262ba0c29528bd7015a7..d06a7071e1d7cda2ae7aef696857d97b12ff764d 100644 (file)
@@ -5,30 +5,32 @@ $(PLATFORM): all
 
 SRC  = pluto.c rings.c bit.c
 
+LIBS = pluto.$(LIBEXT) rings.$(LIBEXT) bit.$(LIBEXT)
+
 ifeq ($(USE_READLINE), yes)
-SRC += editline.c
+LIBS += editline.$(LIBEXT)
 endif
 
-LIBS = $(SRC:.c=.$(LIBEXT)) 
-
 libraries: $(LIBS)
 
 install:   libraries
        mkdir -p $(TARGET_LUA_CPATH)
        cp $(LIBS) $(TARGET_LUA_CPATH)
 
-# TODO [EVE] there is still a question, how to remove dlls,
-# cause clean knows nothing about platform
 clean:
        -rm *.o *.$(LIBEXT)
 
-.PHONY: libraries install clean
-
 ifeq ($(USE_READLINE), yes)
 editline.$(LIBEXT): editline.$(OBJEXT)
        $(MKLIB) -o $@ $+ $(LDFLAGS) -lhistory -lreadline
 endif
 
+
+pluto.$(LIBEXT): pluto/pluto.c pluto/pdep.c pluto/lzio.c
+       $(MKLIB) -o $@ $(LDFLAGS) -I ../$(LUA_VM_DIR) -I pluto $+
+
 %.$(LIBEXT): %.$(OBJEXT)
        $(MKLIB) -o $@ $+ $(LDFLAGS)
 
+.PHONY: libraries install clean
+
diff --git a/src/binlibs/pluto.c b/src/binlibs/pluto.c
deleted file mode 100644 (file)
index b69f98d..0000000
+++ /dev/null
@@ -1,1528 +0,0 @@
-/* $Id$ */
-
-/* Pluto - Heavy-duty persistence for Lua
- * Copyright (C) 2004 by Ben Sunshine-Hill, and released into the public
- * domain. People making use of this software as part of an application
- * are politely requested to email the author at sneftel@gmail.com
- * with a brief description of the application, primarily to satisfy his
- * curiosity.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "lua.h"
-#include "pluto.h"
-
-#include "lapi.h"
-#include "ldo.h"
-#include "lfunc.h"
-#include "lgc.h"
-#include "llimits.h"
-#include "lmem.h"
-#include "lobject.h"
-#include "lopcodes.h"
-#include "lstate.h"
-#include "lstring.h"
-#include "lauxlib.h"
-
-#include <string.h>
-
-
-
-/* #define PLUTO_DEBUG */
-
-
-
-
-#ifdef PLUTO_DEBUG
-#include <stdio.h>
-#endif
-
-#define PLUTO_TPERMANENT 101
-
-#define verify(x) { int v = (int)((x)); v=v; lua_assert(v); }
-
-typedef struct PersistInfo_t {
-       lua_State *L;
-       int counter;
-       lua_Chunkwriter writer;
-       void *ud;
-#ifdef PLUTO_DEBUG
-       int level;
-#endif
-} PersistInfo;
-
-#ifdef PLUTO_DEBUG
-void printindent(int indent)
-{
-       int il;
-       for(il=0; il<indent; il++) {
-               printf("  ");
-       }
-}
-#endif
-
-/* Mutual recursion requires prototype */
-static void persist(PersistInfo *pi);
-
-/* A simple reimplementation of the unfortunately static function luaA_index.
- * Does not support the global table, registry, or upvalues. */
-static StkId getobject(lua_State *L, int stackpos)
-{
-       if(stackpos > 0) {
-               lua_assert(L->base+stackpos-1 < L->top);
-               return L->base+stackpos-1;
-       } else {
-               lua_assert(L->top-stackpos >= L->base);
-               return L->top+stackpos;
-       }
-}
-
-/* Choose whether to do a regular or special persistence based on an object's
- * metatable. "default" is whether the object, if it doesn't have a __persist
- * entry, is literally persistable or not.
- * Pushes the unpersist closure and returns true if special persistence is
- * used. */
-static int persistspecialobject(PersistInfo *pi, int defaction)
-{
-                                       /* perms reftbl ... obj */
-       /* Check whether we should persist literally, or via the __persist
-        * metafunction */
-       if(!lua_getmetatable(pi->L, -1)) {
-               if(defaction) {
-                       {
-                               int zero = 0;
-                               pi->writer(pi->L, &zero, sizeof(int), pi->ud);
-                       }
-                       return 0;
-               } else {
-                       lua_pushstring(pi->L, "Type not literally persistable by default");
-                       lua_error(pi->L);
-               }
-       }
-                                       /* perms reftbl sptbl ... obj mt */
-       lua_pushstring(pi->L, "__persist");
-                                       /* perms reftbl sptbl ... obj mt "__persist" */
-       lua_rawget(pi->L, -2);
-                                       /* perms reftbl sptbl ... obj mt __persist? */
-       if(lua_isnil(pi->L, -1)) {
-                                       /* perms reftbl sptbl ... obj mt nil */
-               lua_pop(pi->L, 2);
-                                       /* perms reftbl sptbl ... obj */
-               if(defaction) {
-                       {
-                               int zero = 0;
-                               pi->writer(pi->L, &zero, sizeof(int), pi->ud);
-                       }
-                       return 0;
-               } else {
-                       lua_pushstring(pi->L, "Type not literally persistable by default");
-                       lua_error(pi->L);
-                       return 0; /* not reached */
-               }
-       } else if(lua_isboolean(pi->L, -1)) {
-                                       /* perms reftbl sptbl ... obj mt bool */
-               if(lua_toboolean(pi->L, -1)) {
-                                       /* perms reftbl sptbl ... obj mt true */
-                       lua_pop(pi->L, 2);
-                                       /* perms reftbl sptbl ... obj */
-                       {
-                               int zero = 0;
-                               pi->writer(pi->L, &zero, sizeof(int), pi->ud);
-                       }
-                       return 0;
-               } else {
-                       lua_pushstring(pi->L, "Metatable forbade persistence");
-                       lua_error(pi->L);
-                       return 0; /* not reached */
-               }
-       } else if(!lua_isfunction(pi->L, -1)) {
-               lua_pushstring(pi->L, "__persist not nil, boolean, or function");
-               lua_error(pi->L);
-       }
-                                       /* perms reftbl ... obj mt __persist */
-       lua_pushvalue(pi->L, -3);
-                                       /* perms reftbl ... obj mt __persist obj */
-#ifdef PLUTO_PASS_USERDATA_TO_PERSIST
-       lua_pushlightuserdata(pi->L, (void*)pi->writer);
-       lua_pushlightuserdata(pi->L, pi->ud);
-                                       /* perms reftbl ... obj mt __persist obj ud */
-       lua_call(pi->L, 3, 1);
-                                       /* perms reftbl ... obj mt func? */
-#else
-       lua_call(pi->L, 1, 1);
-                                       /* perms reftbl ... obj mt func? */
-#endif
-                                       /* perms reftbl ... obj mt func? */
-       if(!lua_isfunction(pi->L, -1)) {
-               lua_pushstring(pi->L, "__persist function did not return a function");
-               lua_error(pi->L);
-       }
-                                       /* perms reftbl ... obj mt func */
-       {
-               int one = 1;
-               pi->writer(pi->L, &one, sizeof(int), pi->ud);
-       }
-       persist(pi);
-                                       /* perms reftbl ... obj mt func */
-       lua_pop(pi->L, 2);
-                                       /* perms reftbl ... obj */
-       return 1;
-}
-
-static void persisttable(PersistInfo *pi)
-{
-                                       /* perms reftbl ... tbl */
-       if(persistspecialobject(pi, 1)) {
-                                       /* perms reftbl ... tbl */
-               return;
-       }
-                                       /* perms reftbl ... tbl */
-       /* First, persist the metatable (if any) */
-       if(!lua_getmetatable(pi->L, -1)) {
-               lua_pushnil(pi->L);
-       }
-                                       /* perms reftbl ... tbl mt/nil */
-       persist(pi);
-       lua_pop(pi->L, 1);
-                                       /* perms reftbl ... tbl */
-
-       /* Now, persist all k/v pairs */
-       lua_pushnil(pi->L);
-                                       /* perms reftbl ... tbl nil */
-       while(lua_next(pi->L, -2)) {
-                                       /* perms reftbl ... tbl k v */
-               lua_pushvalue(pi->L, -2);
-                                       /* perms reftbl ... tbl k v k */
-               persist(pi);
-               lua_pop(pi->L, 1);
-                                       /* perms reftbl ... tbl k v */
-               persist(pi);
-               lua_pop(pi->L, 1);
-                                       /* perms reftbl ... tbl k */
-       }
-                                       /* perms reftbl ... tbl */
-       /* Terminate list */
-       lua_pushnil(pi->L);
-                                       /* perms reftbl ... tbl nil */
-       persist(pi);
-       lua_pop(pi->L, 1);
-                                       /* perms reftbl ... tbl */
-}
-
-static void persistuserdata(PersistInfo *pi) {
-                                       /* perms reftbl ... udata */
-       if(persistspecialobject(pi, 0)) {
-                                       /* perms reftbl ... udata */
-               return;
-       } else {
-       /* Use literal persistence */
-               size_t length = uvalue(getobject(pi->L, -1))->len;
-               pi->writer(pi->L, &length, sizeof(size_t), pi->ud);
-               pi->writer(pi->L, lua_touserdata(pi->L, -1), length, pi->ud);
-               if(!lua_getmetatable(pi->L, -1)) {
-                                       /* perms reftbl ... udata */
-                       lua_pushnil(pi->L);
-                                       /* perms reftbl ... udata mt/nil */
-               }
-               persist(pi);
-               lua_pop(pi->L, 1);
-                                       /* perms reftbl ... udata */
-       }
-}
-
-
-static Proto *toproto(lua_State *L, int stackpos)
-{
-       return gco2p(getobject(L, stackpos)->value.gc);
-}
-
-static UpVal *toupval(lua_State *L, int stackpos)
-{
-       return gco2uv(getobject(L, stackpos)->value.gc);
-}
-
-static void pushproto(lua_State *L, Proto *proto)
-{
-       TValue o;
-       setptvalue(L, &o, proto);
-       luaA_pushobject(L, &o);
-}
-
-#define setuvvalue(L,obj,x) \
-  { TValue *i_o=(obj); \
-    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUPVAL; \
-    checkliveness(G(L),i_o); }
-
-static void pushupval(lua_State *L, UpVal *upval)
-{
-       TValue o;
-       setuvvalue(L, &o, upval);
-       luaA_pushobject(L, &o);
-}
-
-static void pushclosure(lua_State *L, Closure *closure)
-{
-       TValue o;
-       setclvalue(L, &o, closure);
-       luaA_pushobject(L, &o);
-}
-
-static void persistfunction(PersistInfo *pi)
-{
-                                       /* perms reftbl ... func */
-       Closure *cl = clvalue(getobject(pi->L, -1));
-       if(cl->c.isC) {
-               /* It's a C function. For now, we aren't going to allow
-                * persistence of C closures, even if the "C proto" is
-                * already in the permanents table. */
-               lua_pushstring(pi->L, "Attempt to persist a C function");
-               lua_error(pi->L);
-       } else {
-               /* It's a Lua closure. */
-               {
-                       /* We don't really _NEED_ the number of upvals,
-                        * but it'll simplify things a bit */
-                       pi->writer(pi->L, &cl->l.p->nups, sizeof(lu_byte), pi->ud);
-               }
-               /* Persist prototype */
-               {
-                       pushproto(pi->L, cl->l.p);
-                                       /* perms reftbl ... func proto */
-                       persist(pi);
-                       lua_pop(pi->L, 1);
-                                       /* perms reftbl ... func */
-               }
-               /* Persist upvalue values (not the upvalue objects
-                * themselves) */
-               {
-                       int i;
-                       for(i=0; i<cl->l.p->nups; i++) {
-                                       /* perms reftbl ... func */
-                               pushupval(pi->L, cl->l.upvals[i]);
-                                       /* perms reftbl ... func upval */
-                               persist(pi);
-                               lua_pop(pi->L, 1);
-                                       /* perms reftbl ... func */
-                       }
-                                       /* perms reftbl ... func */
-               }
-               /* Persist function environment */
-               {
-                       lua_getfenv(pi->L, -1);
-                                       /* perms reftbl ... func fenv */
-                       if(lua_equal(pi->L, -1, LUA_GLOBALSINDEX)) {
-                               /* Function has the default fenv */
-                                       /* perms reftbl ... func _G */
-                               lua_pop(pi->L, 1);
-                                       /* perms reftbl ... func */
-                               lua_pushnil(pi->L);
-                                       /* perms reftbl ... func nil */
-                       }
-                                       /* perms reftbl ... func fenv/nil */
-                       persist(pi);
-                       lua_pop(pi->L, 1);
-                                       /* perms reftbl ... func */
-               }
-       }
-}
-
-
-/* Upvalues are tricky. Here's why.
- *
- * A particular upvalue may be either "open", in which case its member v
- * points into a thread's stack, or "closed" in which case it points to the
- * upvalue itself. An upvalue is closed under any of the following conditions:
- * -- The function that initially declared the variable "local" returns
- * -- The thread in which the closure was created is garbage collected
- *
- * To make things wackier, just because a thread is reachable by Lua doesn't
- * mean it's in our root set. We need to be able to treat an open upvalue
- * from an unreachable thread as a closed upvalue.
- *
- * The solution:
- * (a) For the purposes of persisting, don't indicate whether an upvalue is
- * closed or not.
- * (b) When unpersisting, pretend that all upvalues are closed.
- * (c) When persisting, persist all open upvalues referenced by a thread
- * that is persisted, and tag each one with the corresponding stack position
- * (d) When unpersisting, "reopen" each of these upvalues as the thread is
- * unpersisted
- */
-static void persistupval(PersistInfo *pi)
-{
-                                       /* perms reftbl ... upval */
-       UpVal *uv = toupval(pi->L, -1);
-
-       /* We can't permit the upval to linger around on the stack, as Lua
-       * will bail if its GC finds it. */
-
-       lua_pop(pi->L, 1);
-                                       /* perms reftbl ... */
-       luaA_pushobject(pi->L, uv->v);
-                                       /* perms reftbl ... obj */
-       persist(pi);
-                                       /* perms reftbl ... obj */
-}
-
-static void persistproto(PersistInfo *pi)
-{
-                                       /* perms reftbl ... proto */
-       Proto *p = toproto(pi->L, -1);
-
-       /* Persist constant refs */
-       {
-               int i;
-               pi->writer(pi->L, &p->sizek, sizeof(int), pi->ud);
-               for(i=0; i<p->sizek; i++) {
-                       luaA_pushobject(pi->L, &p->k[i]);
-                                       /* perms reftbl ... proto const */
-                       persist(pi);
-                       lua_pop(pi->L, 1);
-                                       /* perms reftbl ... proto */
-               }
-       }
-                                       /* perms reftbl ... proto */
-
-       /* serialize inner Proto refs */
-       {
-               int i;
-               pi->writer(pi->L, &p->sizep, sizeof(int), pi->ud);
-               for(i=0; i<p->sizep; i++)
-               {
-                       pushproto(pi->L, p->p[i]);
-                                       /* perms reftbl ... proto subproto */
-                       persist(pi);
-                       lua_pop(pi->L, 1);
-                                       /* perms reftbl ... proto */
-               }
-       }
-                                       /* perms reftbl ... proto */
-       /* Serialize code */
-       {
-               pi->writer(pi->L, &p->sizecode, sizeof(int), pi->ud);
-               pi->writer(pi->L, p->code, sizeof(Instruction) * p->sizecode, pi->ud);
-       }
-       /* Serialize misc values */
-       {
-               pi->writer(pi->L, &p->nups, sizeof(lu_byte), pi->ud);
-               pi->writer(pi->L, &p->numparams, sizeof(lu_byte), pi->ud);
-               pi->writer(pi->L, &p->is_vararg, sizeof(lu_byte), pi->ud);
-               pi->writer(pi->L, &p->maxstacksize, sizeof(lu_byte), pi->ud);
-       }
-       /* We do not currently persist upvalue names, local variable names,
-        * variable lifetimes, line info, or source code. */
-}
-
-/* Copies a stack, but the stack is reversed in the process
- */
-static size_t revappendstack(lua_State *from, lua_State *to)
-{
-       StkId o;
-       for(o=from->top-1; o>=from->stack; o--) {
-               setobj2s(to, to->top, o);
-               to->top++;
-       }
-       return from->top - from->stack;
-}
-
-/* Persist all stack members
- */
-static void persistthread(PersistInfo *pi)
-{
-       size_t posremaining;
-       lua_State *L2;
-                                       /* perms reftbl ... thr */
-       L2 = lua_tothread(pi->L, -1);
-       if(pi->L == L2) {
-               lua_pushstring(pi->L, "Can't persist currently running thread");
-               lua_error(pi->L);
-               return; /* not reached */
-       }
-
-       /* Persist the stack */
-       posremaining = revappendstack(L2, pi->L);
-                                       /* perms reftbl ... thr (rev'ed contents of L2) */
-       pi->writer(pi->L, &posremaining, sizeof(size_t), pi->ud);
-       for(; posremaining > 0; posremaining--) {
-               persist(pi);
-               lua_pop(pi->L, 1);
-       }
-                                       /* perms reftbl ... thr */
-       /* Now, persist the CallInfo stack. */
-       {
-               size_t i, numframes = (L2->ci - L2->base_ci) + 1;
-               pi->writer(pi->L, &numframes, sizeof(size_t), pi->ud);
-               for(i=0; i<numframes; i++) {
-                       CallInfo *ci = L2->base_ci + i;
-                       size_t stackbase = ci->base - L2->stack;
-                       size_t stackfunc = ci->func - L2->stack;
-                       size_t stacktop = ci->top - L2->stack;
-                       size_t savedpc = (ci != L2->base_ci) ?
-                               ci->savedpc - ci_func(ci)->l.p->code :
-                               0;
-                       pi->writer(pi->L, &stackbase, sizeof(size_t), pi->ud);
-                       pi->writer(pi->L, &stackfunc, sizeof(size_t), pi->ud);
-                       pi->writer(pi->L, &stacktop, sizeof(size_t), pi->ud);
-                       pi->writer(pi->L, &ci->nresults, sizeof(int), pi->ud);
-                       pi->writer(pi->L, &savedpc, sizeof(size_t), pi->ud);
-               }
-       }
-
-       /* Serialize the state's other parameters, with the exception of upval stuff */
-       {
-               size_t stackbase = L2->base - L2->stack;
-               size_t stacktop = L2->top - L2->stack;
-               lua_assert(L2->nCcalls <= 1);
-               pi->writer(pi->L, &L2->status, sizeof(lu_byte), pi->ud);
-               pi->writer(pi->L, &stackbase, sizeof(size_t), pi->ud);
-               pi->writer(pi->L, &stacktop, sizeof(size_t), pi->ud);
-               pi->writer(pi->L, &L2->errfunc, sizeof(ptrdiff_t), pi->ud);
-       }
-
-       /* Finally, record upvalues which need to be reopened */
-       /* See the comment above persistupval() for why we do this */
-       {
-               GCObject *gco;
-               UpVal *uv;
-                                       /* perms reftbl ... thr */
-               for(gco = L2->openupval; gco != NULL; gco = uv->next) {
-                       size_t stackpos;
-                       uv = gco2uv(gco);
-
-                       /* Make sure upvalue is really open */
-                       lua_assert(uv->v != &uv->u.value);
-                       pushupval(pi->L, uv);
-                                       /* perms reftbl ... thr uv */
-                       persist(pi);
-                       lua_pop(pi->L, 1);
-                                       /* perms reftbl ... thr */
-                       stackpos = uv->v - L2->stack;
-                       pi->writer(pi->L, &stackpos, sizeof(size_t), pi->ud);
-               }
-                                       /* perms reftbl ... thr */
-               lua_pushnil(pi->L);
-                                       /* perms reftbl ... thr nil */
-               persist(pi);
-               lua_pop(pi->L, 1);
-                                       /* perms reftbl ... thr */
-       }
-                                       /* perms reftbl ... thr */
-}
-
-static void persistboolean(PersistInfo *pi)
-{
-       int b = lua_toboolean(pi->L, -1);
-       pi->writer(pi->L, &b, sizeof(int), pi->ud);
-}
-
-static void persistlightuserdata(PersistInfo *pi)
-{
-       void *p = lua_touserdata(pi->L, -1);
-       pi->writer(pi->L, &p, sizeof(void *), pi->ud);
-}
-
-static void persistnumber(PersistInfo *pi)
-{
-       lua_Number n = lua_tonumber(pi->L, -1);
-       pi->writer(pi->L, &n, sizeof(lua_Number), pi->ud);
-}
-
-static void persiststring(PersistInfo *pi)
-{
-       size_t length = lua_strlen(pi->L, -1);
-       pi->writer(pi->L, &length, sizeof(size_t), pi->ud);
-       pi->writer(pi->L, lua_tostring(pi->L, -1), length, pi->ud);
-}
-
-/* Top-level delegating persist function
- */
-static void persist(PersistInfo *pi)
-{
-                                       /* perms reftbl ... obj */
-       /* If the object has already been written, write a reference to it */
-       lua_pushvalue(pi->L, -1);
-                                       /* perms reftbl ... obj obj */
-       lua_rawget(pi->L, 2);
-                                       /* perms reftbl ... obj ref? */
-       if(!lua_isnil(pi->L, -1)) {
-                                       /* perms reftbl ... obj ref */
-               int zero = 0;
-               int ref = (int)lua_touserdata(pi->L, -1);
-               pi->writer(pi->L, &zero, sizeof(int), pi->ud);
-               pi->writer(pi->L, &ref, sizeof(int), pi->ud);
-               lua_pop(pi->L, 1);
-                                       /* perms reftbl ... obj ref */
-#ifdef PLUTO_DEBUG
-               printindent(pi->level);
-               printf("0 %d\n", ref);
-#endif
-               return;
-       }
-                                       /* perms reftbl ... obj nil */
-       lua_pop(pi->L, 1);
-                                       /* perms reftbl ... obj */
-       /* If the object is nil, write the pseudoreference 0 */
-       if(lua_isnil(pi->L, -1)) {
-               int zero = 0;
-               /* firsttime */
-               pi->writer(pi->L, &zero, sizeof(int), pi->ud);
-               /* ref */
-               pi->writer(pi->L, &zero, sizeof(int), pi->ud);
-#ifdef PLUTO_DEBUG
-               printindent(pi->level);
-               printf("0 0\n");
-#endif
-               return;
-       }
-       {
-               /* indicate that it's the first time */
-               int one = 1;
-               pi->writer(pi->L, &one, sizeof(int), pi->ud);
-       }
-       lua_pushvalue(pi->L, -1);
-                                       /* perms reftbl ... obj obj */
-       lua_pushlightuserdata(pi->L, (void*)(++(pi->counter)));
-                                       /* perms reftbl ... obj obj ref */
-       lua_rawset(pi->L, 2);
-                                       /* perms reftbl ... obj */
-
-       pi->writer(pi->L, &pi->counter, sizeof(int), pi->ud);
-
-
-       /* At this point, we'll give the permanents table a chance to play. */
-       {
-               lua_pushvalue(pi->L, -1);
-                                       /* perms reftbl ... obj obj */
-               lua_gettable(pi->L, 1);
-                                       /* perms reftbl ... obj permkey? */
-               if(!lua_isnil(pi->L, -1)) {
-                                       /* perms reftbl ... obj permkey */
-                       int type = PLUTO_TPERMANENT;
-#ifdef PLUTO_DEBUG
-                       printindent(pi->level);
-                       printf("1 %d PERM\n", pi->counter);
-                       pi->level++;
-#endif
-                       pi->writer(pi->L, &type, sizeof(int), pi->ud);
-                       persist(pi);
-                       lua_pop(pi->L, 1);
-                                       /* perms reftbl ... obj */
-#ifdef PLUTO_DEBUG
-                       pi->level--;
-#endif
-                       return;
-               } else {
-                                       /* perms reftbl ... obj nil */
-                       lua_pop(pi->L, 1);
-                                       /* perms reftbl ... obj */
-               }
-                                       /* perms reftbl ... obj */
-       }
-       {
-               int type = lua_type(pi->L, -1);
-               pi->writer(pi->L, &type, sizeof(int), pi->ud);
-
-#ifdef PLUTO_DEBUG
-               printindent(pi->level);
-               printf("1 %d %d\n", pi->counter, type);
-               pi->level++;
-#endif
-       }
-
-       switch(lua_type(pi->L, -1)) {
-               case LUA_TBOOLEAN:
-                       persistboolean(pi);
-                       break;
-               case LUA_TLIGHTUSERDATA:
-                       persistlightuserdata(pi);
-                       break;
-               case LUA_TNUMBER:
-                       persistnumber(pi);
-                       break;
-               case LUA_TSTRING:
-                       persiststring(pi);
-                       break;
-               case LUA_TTABLE:
-                       persisttable(pi);
-                       break;
-               case LUA_TFUNCTION:
-                       persistfunction(pi);
-                       break;
-               case LUA_TTHREAD:
-                       persistthread(pi);
-                       break;
-               case LUA_TPROTO:
-                       persistproto(pi);
-                       break;
-               case LUA_TUPVAL:
-                       persistupval(pi);
-                       break;
-               case LUA_TUSERDATA:
-                       persistuserdata(pi);
-                       break;
-               default:
-                       lua_assert(0);
-       }
-#ifdef PLUTO_DEBUG
-       pi->level--;
-#endif
-}
-
-void pluto_persist(lua_State *L, lua_Chunkwriter writer, void *ud)
-{
-       PersistInfo pi;
-
-       pi.counter = 0;
-       pi.L = L;
-       pi.writer = writer;
-       pi.ud = ud;
-#ifdef PLUTO_DEBUG
-       pi.level = 0;
-#endif
-
-                                       /* perms? rootobj? ...? */
-       lua_assert(lua_gettop(L) == 2);
-                                       /* perms rootobj */
-       lua_assert(!lua_isnil(L, 2));
-                                       /* perms rootobj */
-       lua_newtable(L);
-                                       /* perms rootobj reftbl */
-
-       /* Now we're going to make the table weakly keyed. This prevents the
-        * GC from visiting it and trying to mark things it doesn't want to
-        * mark in tables, e.g. upvalues. All objects in the table are
-        * a priori reachable, so it doesn't matter that we do this. */
-       lua_newtable(L);
-                                       /* perms rootobj reftbl mt */
-       lua_pushstring(L, "__mode");
-                                       /* perms rootobj reftbl mt "__mode" */
-       lua_pushstring(L, "k");
-                                       /* perms rootobj reftbl mt "__mode" "k" */
-       lua_settable(L, 4);
-                                       /* perms rootobj reftbl mt */
-       lua_setmetatable(L, 3);
-                                       /* perms rootobj reftbl */
-       lua_insert(L, 2);
-                                       /* perms reftbl rootobj */
-       persist(&pi);
-                                       /* perms reftbl rootobj */
-       lua_remove(L, 2);
-                                       /* perms rootobj */
-}
-
-typedef struct WriterInfo_t {
-       char* buf;
-       size_t buflen;
-} WriterInfo;
-
-static int bufwriter (lua_State *L, const void* p, size_t sz, void* ud) {
-       const char* cp = (const char*)p;
-       WriterInfo *wi = (WriterInfo *)ud;
-
-       luaM_reallocvector(L, wi->buf, wi->buflen, wi->buflen+sz, char);
-       while(sz)
-       {
-               /* how dearly I love ugly C pointer twiddling */
-               wi->buf[wi->buflen++] = *cp++;
-               sz--;
-       }
-       return 0;
-}
-
-int persist_l(lua_State *L)
-{
-                                       /* perms? rootobj? ...? */
-       WriterInfo wi;
-
-       wi.buf = NULL;
-       wi.buflen = 0;
-
-       lua_settop(L, 2);
-                                       /* perms? rootobj? */
-       luaL_checktype(L, 1, LUA_TTABLE);
-                                       /* perms rootobj? */
-       luaL_checktype(L, 1, LUA_TTABLE);
-                                       /* perms rootobj */
-
-       pluto_persist(L, bufwriter, &wi);
-
-       lua_settop(L, 0);
-                                       /* (empty) */
-       lua_pushlstring(L, wi.buf, wi.buflen);
-                                       /* str */
-       luaM_freearray(L, wi.buf, wi.buflen, char);
-       return 1;
-}
-
-typedef struct UnpersistInfo_t {
-       lua_State *L;
-       ZIO zio;
-#ifdef PLUTO_DEBUG
-       int level;
-#endif
-} UnpersistInfo;
-
-static void unpersist(UnpersistInfo *upi);
-
-/* The object is left on the stack. This is primarily used by unpersist, but
- * may be used by GCed objects that may incur cycles in order to preregister
- * the object. */
-static void registerobject(int ref, UnpersistInfo *upi)
-{
-                                       /* perms reftbl ... obj */
-       lua_pushlightuserdata(upi->L, (void*)ref);
-                                       /* perms reftbl ... obj ref */
-       lua_pushvalue(upi->L, -2);
-                                       /* perms reftbl ... obj ref obj */
-       lua_settable(upi->L, 2);
-                                       /* perms reftbl ... obj */
-}
-
-static void unpersistboolean(UnpersistInfo *upi)
-{
-                                       /* perms reftbl ... */
-       int b;
-       verify(luaZ_read(&upi->zio, &b, sizeof(int)) == 0);
-       lua_pushboolean(upi->L, b);
-                                       /* perms reftbl ... bool */
-}
-
-static void unpersistlightuserdata(UnpersistInfo *upi)
-{
-                                       /* perms reftbl ... */
-       void *p;
-       verify(luaZ_read(&upi->zio, &p, sizeof(void *)) == 0);
-       lua_pushlightuserdata(upi->L, p);
-                                       /* perms reftbl ... ludata */
-}
-
-static void unpersistnumber(UnpersistInfo *upi)
-{
-                                       /* perms reftbl ... */
-       lua_Number n;
-       verify(luaZ_read(&upi->zio, &n, sizeof(lua_Number)) == 0);
-       lua_pushnumber(upi->L, n);
-                                       /* perms reftbl ... num */
-}
-
-static void unpersiststring(UnpersistInfo *upi)
-{
-                                       /* perms reftbl sptbl ref */
-       int length;
-       char* string;
-       verify(luaZ_read(&upi->zio, &length, sizeof(int)) == 0);
-       string = luaM_newvector(upi->L, length, char);
-       verify(luaZ_read(&upi->zio, string, length) == 0);
-       lua_pushlstring(upi->L, string, length);
-                                       /* perms reftbl sptbl ref str */
-       luaM_freearray(upi->L, string, length, char);
-}
-
-static void unpersistspecialtable(int ref, UnpersistInfo *upi)
-{
-                                       /* perms reftbl ... */
-       unpersist(upi);
-                                       /* perms reftbl ... spfunc? */
-       lua_assert(lua_isfunction(upi->L, -1));
-                                       /* perms reftbl ... spfunc */
-       lua_call(upi->L, 0, 1);
-                                       /* perms reftbl ... tbl? */
-       lua_assert(lua_istable(upi->L, -1));
-                                       /* perms reftbl ... tbl */
-}
-
-static void unpersistliteraltable(int ref, UnpersistInfo *upi)
-{
-                                       /* perms reftbl ... */
-       /* Preregister table for handling of cycles */
-       lua_newtable(upi->L);
-                                       /* perms reftbl ... tbl */
-       registerobject(ref, upi);
-                                       /* perms reftbl ... tbl */
-       /* Unpersist metatable */
-       {
-               unpersist(upi);
-                                       /* perms reftbl ... tbl mt/nil? */
-               if(lua_istable(upi->L, -1)) {
-                                       /* perms reftbl ... tbl mt */
-                       lua_setmetatable(upi->L, -2);
-                                       /* perms reftbl ... tbl */
-               } else {
-                                       /* perms reftbl ... tbl nil? */
-                       lua_assert(lua_isnil(upi->L, -1));
-                                       /* perms reftbl ... tbl nil */
-                       lua_pop(upi->L, 1);
-                                       /* perms reftbl ... tbl */
-               }
-                                       /* perms reftbl ... tbl */
-       }
-
-       while(1)
-       {
-                                       /* perms reftbl ... tbl */
-               unpersist(upi);
-                                       /* perms reftbl ... tbl key/nil */
-               if(lua_isnil(upi->L, -1)) {
-                                       /* perms reftbl ... tbl nil */
-                       lua_pop(upi->L, 1);
-                                       /* perms reftbl ... tbl */
-                       break;
-               }
-                                       /* perms reftbl ... tbl key */
-               unpersist(upi);
-                                       /* perms reftbl ... tbl key value? */
-               lua_assert(!lua_isnil(upi->L, -1));
-                                       /* perms reftbl ... tbl key value */
-               lua_rawset(upi->L, -3);
-                                       /* perms reftbl ... tbl */
-       }
-}
-
-static void unpersisttable(int ref, UnpersistInfo *upi)
-{
-                                       /* perms reftbl ... */
-       {
-               int isspecial;
-               verify(luaZ_read(&upi->zio, &isspecial, sizeof(int)) == 0);
-               if(isspecial) {
-                       unpersistspecialtable(ref, upi);
-                                       /* perms reftbl ... tbl */
-               } else {
-                       unpersistliteraltable(ref, upi);
-                                       /* perms reftbl ... tbl */
-               }
-                                       /* perms reftbl ... tbl */
-       }
-}
-
-static UpVal *makeupval(lua_State *L, int stackpos)
-{
-       UpVal *uv = luaM_new(L, UpVal);
-       luaC_link(L, (GCObject*)uv, LUA_TUPVAL);
-       uv->tt = LUA_TUPVAL;
-       uv->v = &uv->u.value;
-       uv->u.l.prev = NULL;
-       uv->u.l.next = NULL;
-       setobj(L, uv->v, getobject(L, stackpos));
-       return uv;
-}
-
-static Proto *makefakeproto(lua_State *L, lu_byte nups)
-{
-       Proto *p = luaF_newproto(L);
-       p->sizelineinfo = 1;
-       p->lineinfo = luaM_newvector(L, 1, int);
-       p->lineinfo[0] = 1;
-       p->sizecode = 1;
-       p->code = luaM_newvector(L, 1, Instruction);
-       p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0);
-       p->source = luaS_newlstr(L, "", 0);
-       p->maxstacksize = 2;
-       p->nups = nups;
-       p->sizek = 0;
-       p->sizep = 0;
-
-       return p;
-}
-
-/* The GC is not fond of finding upvalues in tables. We get around this
- * during persistence using a weakly keyed table, so that the GC doesn't
- * bother to mark them. This won't work in unpersisting, however, since
- * if we make the values weak they'll be collected (since nothing else
- * references them). Our solution, during unpersisting, is to represent
- * upvalues as dummy functions, each with one upvalue. */
-static void boxupval_start(lua_State *L)
-{
-       LClosure *lcl;
-       lcl = (LClosure*)luaF_newLclosure(L, 1, hvalue(&L->l_gt));
-       pushclosure(L, (Closure*)lcl);
-                                       /* ... func */
-       lcl->p = makefakeproto(L, 1);
-
-       /* Temporarily initialize the upvalue to nil */
-
-       lua_pushnil(L);
-       lcl->upvals[0] = makeupval(L, -1);
-       lua_pop(L, 1);
-}
-
-static void boxupval_finish(lua_State *L)
-{
-                                       /* ... func upval */
-       UpVal *uv;
-       LClosure *lcl = (LClosure *) clvalue(getobject(L, -2));
-
-       uv = toupval(L, -1);
-       lua_pop(L, 1);
-                                       /* ... func */
-       lcl->p->nups = 1;
-       lcl->upvals[0] = uv;
-}
-
-
-static void unboxupval(lua_State *L)
-{
-                                       /* ... func */
-       LClosure *lcl;
-       UpVal *uv;
-
-       lcl = (LClosure*)clvalue(getobject(L, -1));
-       uv = lcl->upvals[0];
-       lua_pop(L, 1);
-                                       /* ... */
-       pushupval(L, uv);
-                                       /* ... upval */
-}
-
-static void unpersistfunction(int ref, UnpersistInfo *upi)
-{
-                                       /* perms reftbl ... */
-       LClosure *lcl;
-       int i;
-       lu_byte nupvalues;
-
-       verify(luaZ_read(&upi->zio, &nupvalues, sizeof(lu_byte)) == 0);
-
-       lcl = (LClosure*)luaF_newLclosure(upi->L, nupvalues, hvalue(&upi->L->l_gt));
-       pushclosure(upi->L, (Closure*)lcl);
-
-                                       /* perms reftbl ... func */
-       /* Put *some* proto in the closure, before the GC can find it */
-       lcl->p = makefakeproto(upi->L, nupvalues);
-
-       /* Also, we need to temporarily fill the upvalues */
-       lua_pushnil(upi->L);
-                                       /* perms reftbl ... func nil */
-       for(i=0; i<nupvalues; i++) {
-               lcl->upvals[i] = makeupval(upi->L, -1);
-       }
-       lua_pop(upi->L, 1);
-                                       /* perms reftbl ... func */
-
-       /* I can't see offhand how a function would ever get to be self-
-        * referential, but just in case let's register it early */
-       registerobject(ref, upi);
-
-       /* Now that it's safe, we can get the real proto */
-       unpersist(upi);
-                                       /* perms reftbl ... func proto? */
-       lua_assert(lua_type(upi->L, -1) == LUA_TPROTO);
-                                       /* perms reftbl ... func proto */
-       lcl->p = toproto(upi->L, -1);
-       lua_pop(upi->L, 1);
-                                       /* perms reftbl ... func */
-
-       for(i=0; i<nupvalues; i++) {
-                                       /* perms reftbl ... func */
-               unpersist(upi);
-                                       /* perms reftbl ... func func2 */
-               unboxupval(upi->L);
-                                       /* perms reftbl ... func upval */
-               lcl->upvals[i] = toupval(upi->L, -1);
-               lua_pop(upi->L, 1);
-                                       /* perms reftbl ... func */
-       }
-                                       /* perms reftbl ... func */
-
-       /* Finally, the fenv */
-       unpersist(upi);
-                                       /* perms reftbl ... func fenv/nil? */
-       lua_assert(lua_type(upi->L, -1) == LUA_TNIL ||
-               lua_type(upi->L, -1) == LUA_TTABLE);
-                                       /* perms reftbl ... func fenv/nil */
-       if(!lua_isnil(upi->L, -1)) {
-                                       /* perms reftbl ... func fenv */
-               lua_setfenv(upi->L, -2);
-                                       /* perms reftbl ... func */
-       } else {
-                                       /* perms reftbl ... func nil */
-               lua_pop(upi->L, 1);
-                                       /* perms reftbl ... func */
-       }
-                                       /* perms reftbl ... func */
-}
-
-static void unpersistupval(int ref, UnpersistInfo *upi)
-{
-                                       /* perms reftbl ... */
-       UpVal *uv;
-
-       boxupval_start(upi->L);
-                                       /* perms reftbl ... func */
-       registerobject(ref, upi);
-
-       unpersist(upi);
-                                       /* perms reftbl ... func obj */
-       uv = makeupval(upi->L, -1);
-       lua_pop(upi->L, 1);
-                                       /* perms reftbl ... func */
-       pushupval(upi->L, uv);
-                                       /* perms reftbl ... func upval */
-       boxupval_finish(upi->L);
-                                       /* perms reftbl ... func */
-}
-
-static void unpersistproto(int ref, UnpersistInfo *upi)
-{
-                                       /* perms reftbl ... */
-       Proto *p;
-       int i;
-       int sizep, sizek;
-
-       /* We have to be careful. The GC expects a lot out of protos. In
-        * particular, we need to give the function a valid string for its
-        * source, and valid code, even before we actually read in the real
-        * code. */
-       TString *source = luaS_newlstr(upi->L, "", 0);
-       p = luaF_newproto(upi->L);
-       p->source = source;
-       p->sizecode=1;
-       p->code = luaM_newvector(upi->L, 1, Instruction);
-       p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0);
-       p->maxstacksize = 2;
-       p->sizek = 0;
-       p->sizep = 0;
-
-
-       pushproto(upi->L, p);
-                                       /* perms reftbl ... proto */
-       /* We don't need to register early, since protos can never ever be
-        * involved in cyclic references */
-
-       /* Read in constant references */
-       {
-               verify(luaZ_read(&upi->zio, &sizek, sizeof(int)) == 0);
-               luaM_reallocvector(upi->L, p->k, 0, sizek, TValue);
-               for(i=0; i<sizek; i++) {
-                                       /* perms reftbl ... proto */
-                       unpersist(upi);
-                                       /* perms reftbl ... proto k */
-                       setobj2s(upi->L, &p->k[i], getobject(upi->L, -1));
-                       p->sizek++;
-                       lua_pop(upi->L, 1);
-                                       /* perms reftbl ... proto */
-               }
-                                       /* perms reftbl ... proto */
-       }
-       /* Read in sub-proto references */
-       {
-               verify(luaZ_read(&upi->zio, &sizep, sizeof(int)) == 0);
-               luaM_reallocvector(upi->L, p->p, 0, sizep, Proto*);
-               for(i=0; i<sizep; i++) {
-                                       /* perms reftbl ... proto */
-                       unpersist(upi);
-                                       /* perms reftbl ... proto subproto */
-                       p->p[i] = toproto(upi->L, -1);
-                       p->sizep++;
-                       lua_pop(upi->L, 1);
-                                       /* perms reftbl ... proto */
-               }
-                                       /* perms reftbl ... proto */
-       }
-
-       /* Read in code */
-       {
-               verify(luaZ_read(&upi->zio, &p->sizecode, sizeof(int)) == 0);
-               luaM_reallocvector(upi->L, p->code, 1, p->sizecode, Instruction);
-               verify(luaZ_read(&upi->zio, p->code,
-                       sizeof(Instruction) * p->sizecode) == 0);
-       }
-
-       /* Read in misc values */
-       {
-               verify(luaZ_read(&upi->zio, &p->nups, sizeof(lu_byte)) == 0);
-               verify(luaZ_read(&upi->zio, &p->numparams, sizeof(lu_byte)) == 0);
-               verify(luaZ_read(&upi->zio, &p->is_vararg, sizeof(lu_byte)) == 0);
-               verify(luaZ_read(&upi->zio, &p->maxstacksize, sizeof(lu_byte)) == 0);
-       }
-}
-
-
-/* Does basically the opposite of luaC_link().
- * Right now this function is rather inefficient; it requires traversing the
- * entire root GC set in order to find one object. If the GC list were doubly
- * linked this would be much easier, but there's no reason for Lua to have
- * that. */
-static void gcunlink(lua_State *L, GCObject *gco)
-{
-       GCObject *prevslot;
-       if(G(L)->rootgc == gco) {
-               G(L)->rootgc = G(L)->rootgc->gch.next;
-               return;
-       }
-
-       prevslot = G(L)->rootgc;
-       while(prevslot->gch.next != gco) {
-               lua_assert(prevslot->gch.next != NULL);
-               prevslot = prevslot->gch.next;
-       }
-
-       prevslot->gch.next = prevslot->gch.next->gch.next;
-}
-
-/* FIXME __ALL__ field ordering */
-static void unpersistthread(int ref, UnpersistInfo *upi)
-{
-                                       /* perms reftbl ... */
-       lua_State *L2;
-       size_t stacklimit = 0;
-       L2 = lua_newthread(upi->L);
-                                       /* L1: perms reftbl ... thr */
-                                       /* L2: (empty) */
-       registerobject(ref, upi);
-
-       /* First, deserialize the object stack. */
-       {
-               size_t i, stacksize;
-               verify(luaZ_read(&upi->zio, &stacksize, sizeof(size_t)) == 0);
-               luaD_growstack(L2, (int)stacksize);
-               /* Make sure that the first stack element (a nil, representing
-                * the imaginary top-level C function) is written to the very,
-                * very bottom of the stack */
-               L2->top--;
-               for(i=0; i<stacksize; i++) {
-                       unpersist(upi);
-                                       /* L1: perms reftbl ... thr obj* */
-               }
-               lua_xmove(upi->L, L2, stacksize);
-                                       /* L1: perms reftbl ... thr */
-                                       /* L2: obj* */
-       }
-                                       /* (hereafter, stacks refer to L1) */
-
-       /* Now, deserialize the CallInfo stack. */
-       {
-               size_t i, numframes;
-               verify(luaZ_read(&upi->zio, &numframes, sizeof(size_t)) == 0);
-               luaD_reallocCI(L2,numframes*2);
-               for(i=0; i<numframes; i++) {
-                       CallInfo *ci = L2->base_ci + i;
-                       size_t stackbase, stackfunc, stacktop, savedpc;
-                       verify(luaZ_read(&upi->zio, &stackbase, sizeof(size_t)) == 0);
-                       verify(luaZ_read(&upi->zio, &stackfunc, sizeof(size_t)) == 0);
-                       verify(luaZ_read(&upi->zio, &stacktop, sizeof(size_t)) == 0);
-                       verify(luaZ_read(&upi->zio, &ci->nresults, sizeof(int)) == 0);
-                       verify(luaZ_read(&upi->zio, &savedpc, sizeof(size_t)) == 0);
-                       
-                       if(stacklimit < stacktop)
-                               stacklimit = stacktop;
-                       
-                       ci->base = L2->stack+stackbase;
-                       ci->func = L2->stack+stackfunc;
-                       ci->top = L2->stack+stacktop;
-                       ci->savedpc = (ci != L2->base_ci) ?
-                               ci_func(ci)->l.p->code+savedpc :
-                               0;
-                       ci->tailcalls = 0;
-                       /* Update the pointer each time, to keep the GC
-                        * happy*/
-                       L2->ci = ci;
-               }
-       }
-                                       /* perms reftbl ... thr */
-       /* Deserialize the state's other parameters, with the exception of upval stuff */
-       {
-               size_t stackbase, stacktop;
-               L2->savedpc = L2->ci->savedpc;
-               verify(luaZ_read(&upi->zio, &L2->status, sizeof(lu_byte)) == 0);
-               verify(luaZ_read(&upi->zio, &stackbase, sizeof(size_t)) == 0);
-               verify(luaZ_read(&upi->zio, &stacktop, sizeof(size_t)) == 0);
-               verify(luaZ_read(&upi->zio, &L2->errfunc, sizeof(ptrdiff_t)) == 0);
-               L2->base = L2->stack + stackbase;
-               L2->top = L2->stack + stacktop;
-       }
-       /* Finally, "reopen" upvalues (see persistupval() for why) */
-       {
-               UpVal* uv;
-               GCObject **nextslot = &L2->openupval;
-               global_State *g = G(L2);
-               while(1) {
-                       size_t stackpos;
-                       unpersist(upi);
-                                       /* perms reftbl ... thr uv/nil */
-                       if(lua_isnil(upi->L, -1)) {
-                                       /* perms reftbl ... thr nil */
-                               lua_pop(upi->L, 1);
-                                       /* perms reftbl ... thr */
-                               break;
-                       }
-                                       /* perms reftbl ... thr boxeduv */
-                       unboxupval(upi->L);
-                                       /* perms reftbl ... thr uv */
-                       uv = toupval(upi->L, -1);
-                       lua_pop(upi->L, 1);
-                                       /* perms reftbl ... thr */
-
-                       verify(luaZ_read(&upi->zio, &stackpos, sizeof(size_t)) == 0);
-                       uv->v = L2->stack + stackpos;
-                       gcunlink(upi->L, (GCObject*)uv);
-                       uv->marked = luaC_white(g);
-                       *nextslot = (GCObject*)uv;
-                       nextslot = &uv->next;
-                       uv->u.l.prev = &G(L2)->uvhead;
-                       uv->u.l.next = G(L2)->uvhead.u.l.next;
-                       uv->u.l.next->u.l.prev = uv;
-                       G(L2)->uvhead.u.l.next = uv;
-                       lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
-               }
-               *nextslot = NULL;
-       }
-       
-       /* The stack must be valid at least to the highest value among the CallInfos */
-       /* 'top' and the values up to there must be filled with 'nil' */
-       {
-               StkId o;
-               luaD_checkstack(L2, (int)stacklimit);
-               for (o = L2->top; o <= L2->top + stacklimit; o++)
-                       setnilvalue(o);
-       }
-}
-
-static void unpersistuserdata(int ref, UnpersistInfo *upi)
-{
-                                       /* perms reftbl ... */
-       int isspecial;
-       verify(luaZ_read(&upi->zio, &isspecial, sizeof(int)) == 0);
-       if(isspecial) {
-               unpersist(upi);
-                                       /* perms reftbl ... spfunc? */
-               lua_assert(lua_isfunction(upi->L, -1));
-                                       /* perms reftbl ... spfunc */
-#ifdef PLUTO_PASS_USERDATA_TO_PERSIST
-               lua_pushlightuserdata(upi->L, &upi->zio);
-               lua_call(upi->L, 1, 1);
-#else
-               lua_call(upi->L, 0, 1);
-#endif
-                                       /* perms reftbl ... udata? */
-/* This assertion might not be necessary; it's conceivable, for
- * example, that the SP function might decide to return a table
- * with equivalent functionality. For the time being, we'll
- * ignore this possibility in favor of stricter and more testable
- * requirements. */
-               lua_assert(lua_isuserdata(upi->L, -1));
-                                       /* perms reftbl ... udata */
-       } else {
-               size_t length;
-               verify(luaZ_read(&upi->zio, &length, sizeof(size_t)) == 0);
-
-               lua_newuserdata(upi->L, length);
-                                       /* perms reftbl ... udata */
-               registerobject(ref, upi);
-               verify(luaZ_read(&upi->zio, lua_touserdata(upi->L, -1), length) == 0);
-
-               unpersist(upi);
-                                       /* perms reftbl ... udata mt/nil? */
-               lua_assert(lua_istable(upi->L, -1) || lua_isnil(upi->L, -1));
-                                       /* perms reftbl ... udata mt/nil */
-               lua_setmetatable(upi->L, -2);
-                                       /* perms reftbl ... udata */
-       }
-                                       /* perms reftbl ... udata */
-}
-
-static void unpersistpermanent(int ref, UnpersistInfo *upi)
-{
-                                       /* perms reftbl ... */
-       unpersist(upi);
-                                       /* perms reftbl permkey */
-       lua_gettable(upi->L, 1);
-                                       /* perms reftbl perm? */
-       /* We assume currently that the substituted permanent value
-        * shouldn't be nil. This may be a bad assumption. Real-life
-        * experience is needed to evaluate this. */
-       lua_assert(!lua_isnil(upi->L, -1));
-                                       /* perms reftbl perm */
-}
-
-/* For debugging only; not called when lua_assert is empty */
-static int inreftable(lua_State *L, int ref)
-{
-       int res;
-                                       /* perms reftbl ... */
-       lua_pushlightuserdata(L, (void*)ref);
-                                       /* perms reftbl ... ref */
-       lua_gettable(L, 2);
-                                       /* perms reftbl ... obj? */
-       res = !lua_isnil(L, -1);
-       lua_pop(L, 1);
-                                       /* perms reftbl ... */
-       return res;
-}
-
-static void unpersist(UnpersistInfo *upi)
-{
-                                       /* perms reftbl ... */
-       int firstTime;
-       int stacksize = lua_gettop(upi->L); stacksize = stacksize; /* DEBUG */
-       luaZ_read(&upi->zio, &firstTime, sizeof(int));
-       if(firstTime) {
-               int ref;
-               int type;
-               luaZ_read(&upi->zio, &ref, sizeof(int));
-               lua_assert(!inreftable(upi->L, ref));
-               luaZ_read(&upi->zio, &type, sizeof(int));
-#ifdef PLUTO_DEBUG
-               printindent(upi->level);
-               printf("1 %d %d\n", ref, type);
-               upi->level++;
-#endif
-               switch(type) {
-               case LUA_TBOOLEAN:
-                       unpersistboolean(upi);
-                       break;
-               case LUA_TLIGHTUSERDATA:
-                       unpersistlightuserdata(upi);
-                       break;
-               case LUA_TNUMBER:
-                       unpersistnumber(upi);
-                       break;
-               case LUA_TSTRING:
-                       unpersiststring(upi);
-                       break;
-               case LUA_TTABLE:
-                       unpersisttable(ref, upi);
-                       break;
-               case LUA_TFUNCTION:
-                       unpersistfunction(ref, upi);
-                       break;
-               case LUA_TTHREAD:
-                       unpersistthread(ref, upi);
-                       break;
-               case LUA_TPROTO:
-                       unpersistproto(ref, upi);
-                       break;
-               case LUA_TUPVAL:
-                       unpersistupval(ref, upi);
-                       break;
-               case LUA_TUSERDATA:
-                       unpersistuserdata(ref, upi);
-                       break;
-               case PLUTO_TPERMANENT:
-                       unpersistpermanent(ref, upi);
-                       break;
-               default:
-                       lua_assert(0);
-               }
-                                       /* perms reftbl ... obj */
-               lua_assert(lua_type(upi->L, -1) == type ||
-                       type == PLUTO_TPERMANENT ||
-                       /* Remember, upvalues get a special dispensation, as
-                        * described in boxupval */
-                       (lua_type(upi->L, -1) == LUA_TFUNCTION &&
-                               type == LUA_TUPVAL));
-               registerobject(ref, upi);
-                                       /* perms reftbl ... obj */
-#ifdef PLUTO_DEBUG
-               upi->level--;
-#endif
-       } else {
-               int ref;
-               luaZ_read(&upi->zio, &ref, sizeof(int));
-#ifdef PLUTO_DEBUG
-               printindent(upi->level);
-               printf("0 %d\n", ref);
-#endif
-               if(ref == 0) {
-                       lua_pushnil(upi->L);
-                                       /* perms reftbl ... nil */
-               } else {
-                       lua_pushlightuserdata(upi->L, (void*)ref);
-                                       /* perms reftbl ... ref */
-                       lua_gettable(upi->L, 2);
-                                       /* perms reftbl ... obj? */
-                       lua_assert(!lua_isnil(upi->L, -1));
-               }
-                                       /* perms reftbl ... obj/nil */
-       }
-                                       /* perms reftbl ... obj/nil */
-       lua_assert(lua_gettop(upi->L) == stacksize + 1);
-}
-
-void pluto_unpersist(lua_State *L, lua_Chunkreader reader, void *ud)
-{
-       /* We use the graciously provided ZIO (what the heck does the Z stand
-        * for?) library so that we don't have to deal with the reader directly.
-        * Letting the reader function decide how much data to return can be
-        * very unpleasant.
-        */
-       UnpersistInfo upi;
-       upi.L = L;
-#ifdef PLUTO_DEBUG
-       upi.level = 0;
-#endif
-
-       luaZ_init(L, &upi.zio, reader, ud);
-
-                                       /* perms */
-       lua_newtable(L);
-                                       /* perms reftbl */
-       lua_gc(L, LUA_GCSTOP, 0);
-       unpersist(&upi);
-       lua_gc(L, LUA_GCRESTART, 0);
-                                       /* perms reftbl rootobj */
-       lua_replace(L, 2);
-                                       /* perms rootobj  */
-}
-
-typedef struct LoadInfo_t {
-  char *buf;
-  size_t size;
-} LoadInfo;
-
-
-static const char *bufreader(lua_State *L, void *ud, size_t *sz) {
-       LoadInfo *li = (LoadInfo *)ud;
-       if(li->size == 0) {
-               return NULL;
-       }
-       *sz = li->size;
-       li->size = 0;
-       return li->buf;
-}
-
-int unpersist_l(lua_State *L)
-{
-       LoadInfo li;
-       char const *origbuf;
-       char *tempbuf;
-       size_t bufsize;
-                                       /* perms? str? ...? */
-       lua_settop(L, 2);
-                                       /* perms? str? */
-       origbuf = luaL_checklstring(L, 2, &bufsize);
-       tempbuf = luaM_newvector(L, bufsize, char);
-       memcpy(tempbuf, origbuf, bufsize);
-
-       li.buf = tempbuf;
-       li.size = bufsize;
-
-                                       /* perms? str */
-       lua_pop(L, 1);
-                                       /* perms? */
-       luaL_checktype(L, 1, LUA_TTABLE);
-                                       /* perms */
-       pluto_unpersist(L, bufreader, &li);
-                                       /* perms rootobj */
-       luaM_freearray(L, tempbuf, bufsize, char);
-       return 1;
-}
-
-static luaL_reg pluto_reg[] = {
-       { "persist", persist_l },
-       { "unpersist", unpersist_l },
-       { NULL, NULL }
-};
-
-LUALIB_API int luaopen_pluto(lua_State *L) {
-       luaL_openlib(L, "pluto", pluto_reg, 0);
-       return 1;
-}
-
diff --git a/src/binlibs/pluto.h b/src/binlibs/pluto.h
deleted file mode 100644 (file)
index 6347661..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/* $Id$ */
-
-/* Pluto - Heavy-duty persistence for Lua
- * Copyright (C) 2004 by Ben Sunshine-Hill, and released into the public 
- * domain. People making use of this software as part of an application
- * are politely requested to email the author at sneftel@gmail.com 
- * with a brief description of the application, primarily to satisfy his
- * curiosity.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/* lua.h must be included before this file */
-
-
-void pluto_persist(lua_State *L, lua_Chunkwriter writer, void *ud);
-
-void pluto_unpersist(lua_State *L, lua_Chunkreader reader, void *ud);
-
-LUALIB_API int luaopen_pluto(lua_State *L);
diff --git a/src/binlibs/pluto/lzio.c b/src/binlibs/pluto/lzio.c
new file mode 100644 (file)
index 0000000..7c5ab3b
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $
+** a generic input stream interface
+** See Copyright Notice in lua.h
+*/
+
+
+#include <string.h>
+
+#define lzio_c
+#define LUA_CORE
+
+#include "pdep/pdep.h"
+
+int pdep_fill (ZIO *z) {
+  size_t 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;
+  return char2int(*(z->p++));
+}
+
+
+int pdep_lookahead (ZIO *z) {
+  if (z->n == 0) {
+    if (pdep_fill(z) == EOZ)
+      return EOZ;
+    else {
+      z->n++;  /* pdep_fill removed first byte; put back it */
+      z->p--;
+    }
+  }
+  return char2int(*z->p);
+}
+
+
+void pdep_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) {
+  z->L = L;
+  z->reader = reader;
+  z->data = data;
+  z->n = 0;
+  z->p = NULL;
+}
+
+
+/* --------------------------------------------------------------- read --- */
+size_t pdep_read (ZIO *z, void *b, size_t n) {
+  while (n) {
+    size_t m;
+    if (pdep_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;
+    z->p += m;
+    b = (char *)b + m;
+    n -= m;
+  }
+  return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+char *pdep_openspace (lua_State *L, Mbuffer *buff, size_t n) {
+  if (n > buff->buffsize) {
+    if (n < LUA_MINBUFFER) n = LUA_MINBUFFER;
+    pdep_resizebuffer(L, buff, n);
+  }
+  return buff->buffer;
+}
+
+
diff --git a/src/binlibs/pluto/pdep.c b/src/binlibs/pluto/pdep.c
new file mode 100644 (file)
index 0000000..a32c43b
--- /dev/null
@@ -0,0 +1,112 @@
+/* This file is derived from the Lua source code. Please see lua.h for
+the copyright statement.
+*/
+
+#include "pdep/pdep.h"
+
+#define api_incr_top(L)   {api_check(L, L->top < L->ci->top); L->top++;}
+
+void pdep_pushobject (lua_State *L, const TValue *o) {
+       setobj2s(L, L->top, o);
+       api_incr_top(L);
+}
+
+void *pdep_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);
+       lua_assert((nsize == 0) == (block == NULL));
+       g->totalbytes = (g->totalbytes - osize) + nsize;
+       return block;
+}
+
+void pdep_link (lua_State *L, GCObject *o, lu_byte tt) {
+       global_State *g = G(L);
+       o->gch.next = g->rootgc;
+       g->rootgc = o;
+       o->gch.marked = luaC_white(g);
+       o->gch.tt = tt;
+}
+
+Proto *pdep_newproto (lua_State *L) {
+       Proto *f = pdep_new(L, Proto);
+       pdep_link(L, obj2gco(f), LUA_TPROTO);
+       f->k = NULL;
+       f->sizek = 0;
+       f->p = NULL;
+       f->sizep = 0;
+       f->code = NULL;
+       f->sizecode = 0;
+       f->sizelineinfo = 0;
+       f->sizeupvalues = 0;
+       f->nups = 0;
+       f->upvalues = NULL;
+       f->numparams = 0;
+       f->is_vararg = 0;
+       f->maxstacksize = 0;
+       f->lineinfo = NULL;
+       f->sizelocvars = 0;
+       f->locvars = NULL;
+       f->linedefined = 0;
+       f->lastlinedefined = 0;
+       f->source = NULL;
+       return f;
+}
+
+Closure *pdep_newLclosure (lua_State *L, int nelems, Table *e) {
+       Closure *c = cast(Closure *, pdep_malloc(L, sizeLclosure(nelems)));
+       pdep_link(L, obj2gco(c), LUA_TFUNCTION);
+       c->l.isC = 0;
+       c->l.env = e;
+       c->l.nupvalues = cast_byte(nelems);
+       while (nelems--) c->l.upvals[nelems] = NULL;
+       return c;
+}
+
+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)
+    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->base - oldstack) + L->stack;
+}
+
+
+void pdep_reallocstack (lua_State *L, int newsize) {
+       TValue *oldstack = L->stack;
+       int realsize = newsize + 1 + EXTRA_STACK;
+       lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);
+       pdep_reallocvector(L, L->stack, L->stacksize, realsize, TValue);
+       L->stacksize = realsize;
+       L->stack_last = L->stack+newsize;
+       correctstack(L, oldstack);
+}
+
+void pdep_growstack (lua_State *L, int n) {
+       if (n <= L->stacksize)  /* double size is enough? */
+               pdep_reallocstack(L, 2*L->stacksize);
+       else
+               pdep_reallocstack(L, L->stacksize + n);
+}
+
+void pdep_reallocCI (lua_State *L, int newsize) {
+       CallInfo *oldci = L->base_ci;
+       pdep_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);
+       L->size_ci = newsize;
+       L->ci = (L->ci - oldci) + L->base_ci;
+       L->end_ci = L->base_ci + L->size_ci - 1;
+}
+
+TString *pdep_newlstr (lua_State *L, const char *str, size_t l) {
+       TString *res;
+       lua_pushlstring(L, str, l);
+       res = rawtsvalue(L->top-1);
+       lua_pop(L, 1);
+       return res;
+}
diff --git a/src/binlibs/pluto/pdep/README b/src/binlibs/pluto/pdep/README
new file mode 100644 (file)
index 0000000..3592754
--- /dev/null
@@ -0,0 +1,5 @@
+These files are directly copied from the Lua distribution, with the
+exception of lzio.h, which is s/lua{ZM}/pdep/g and has an include removed.
+
+As such, unlike the rest of Pluto, they are released under the
+same terms as Lua. See "lua.h" for the copyright notice.
diff --git a/src/binlibs/pluto/pdep/lauxlib.h b/src/binlibs/pluto/pdep/lauxlib.h
new file mode 100644 (file)
index 0000000..3425823
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $
+** Auxiliary functions for building Lua libraries
+** See Copyright Notice in lua.h
+*/
+
+
+#ifndef lauxlib_h
+#define lauxlib_h
+
+
+#include <stddef.h>
+#include <stdio.h>
+
+#include "lua.h"
+
+
+#if defined(LUA_COMPAT_GETN)
+LUALIB_API int (luaL_getn) (lua_State *L, int t);
+LUALIB_API void (luaL_setn) (lua_State *L, int t, int n);
+#else
+#define luaL_getn(L,i)          ((int)lua_objlen(L, i))
+#define luaL_setn(L,i,j)        ((void)0)  /* no op! */
+#endif
+
+#if defined(LUA_COMPAT_OPENLIB)
+#define luaI_openlib   luaL_openlib
+#endif
+
+
+/* extra error code for `luaL_load' */
+#define LUA_ERRFILE     (LUA_ERRERR+1)
+
+
+typedef struct luaL_Reg {
+  const char *name;
+  lua_CFunction func;
+} luaL_Reg;
+
+
+
+LUALIB_API void (luaI_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);
+LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
+LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
+LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname);
+LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg);
+LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg,
+                                                          size_t *l);
+LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg,
+                                          const char *def, size_t *l);
+LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg);
+LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def);
+
+LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
+LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
+                                          lua_Integer def);
+
+LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
+LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
+LUALIB_API void (luaL_checkany) (lua_State *L, int narg);
+
+LUALIB_API int   (luaL_newmetatable) (lua_State *L, const char *tname);
+LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
+
+LUALIB_API void (luaL_where) (lua_State *L, int lvl);
+LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
+
+LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
+                                   const char *const lst[]);
+
+LUALIB_API int (luaL_ref) (lua_State *L, int t);
+LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
+
+LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename);
+LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz,
+                                  const char *name);
+LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
+
+LUALIB_API lua_State *(luaL_newstate) (void);
+
+
+LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
+                                                  const char *r);
+
+LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,
+                                         const char *fname, int szhint);
+
+
+
+
+/*
+** ===============================================================
+** some useful macros
+** ===============================================================
+*/
+
+#define luaL_argcheck(L, cond,numarg,extramsg) \
+               ((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))
+#define luaL_checkstring(L,n)  (luaL_checklstring(L, (n), NULL))
+#define luaL_optstring(L,n,d)  (luaL_optlstring(L, (n), (d), NULL))
+#define luaL_checkint(L,n)     ((int)luaL_checkinteger(L, (n)))
+#define luaL_optint(L,n,d)     ((int)luaL_optinteger(L, (n), (d)))
+#define luaL_checklong(L,n)    ((long)luaL_checkinteger(L, (n)))
+#define luaL_optlong(L,n,d)    ((long)luaL_optinteger(L, (n), (d)))
+
+#define luaL_typename(L,i)     lua_typename(L, lua_type(L,(i)))
+
+#define luaL_dofile(L, fn) \
+       (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
+
+#define luaL_dostring(L, s) \
+       (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
+
+#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
+
+#define luaL_opt(L,f,n,d)      (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
+
+/*
+** {======================================================
+** Generic Buffer manipulation
+** =======================================================
+*/
+
+
+
+typedef struct luaL_Buffer {
+  char *p;                     /* current position in buffer */
+  int lvl;  /* number of strings in the stack (level) */
+  lua_State *L;
+  char buffer[LUAL_BUFFERSIZE];
+} luaL_Buffer;
+
+#define luaL_addchar(B,c) \
+  ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
+   (*(B)->p++ = (char)(c)))
+
+/* compatibility only */
+#define luaL_putchar(B,c)      luaL_addchar(B,c)
+
+#define luaL_addsize(B,n)      ((B)->p += (n))
+
+LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);
+LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B);
+LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
+LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);
+LUALIB_API void (luaL_addvalue) (luaL_Buffer *B);
+LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
+
+
+/* }====================================================== */
+
+
+/* compatibility with ref system */
+
+/* pre-defined references */
+#define LUA_NOREF       (-2)
+#define LUA_REFNIL      (-1)
+
+#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \
+      (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0))
+
+#define lua_unref(L,ref)        luaL_unref(L, LUA_REGISTRYINDEX, (ref))
+
+#define lua_getref(L,ref)       lua_rawgeti(L, LUA_REGISTRYINDEX, (ref))
+
+
+#define luaL_reg       luaL_Reg
+
+#endif
+
+
diff --git a/src/binlibs/pluto/pdep/ldo.h b/src/binlibs/pluto/pdep/ldo.h
new file mode 100644 (file)
index 0000000..98fddac
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $
+** Stack and Call structure of Lua
+** See Copyright Notice in lua.h
+*/
+
+#ifndef ldo_h
+#define ldo_h
+
+
+#include "lobject.h"
+#include "lstate.h"
+#include "lzio.h"
+
+
+#define luaD_checkstack(L,n)   \
+  if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \
+    luaD_growstack(L, n); \
+  else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1));
+
+
+#define incr_top(L) {luaD_checkstack(L,1); L->top++;}
+
+#define savestack(L,p)         ((char *)(p) - (char *)L->stack)
+#define restorestack(L,n)      ((TValue *)((char *)L->stack + (n)))
+
+#define saveci(L,p)            ((char *)(p) - (char *)L->base_ci)
+#define restoreci(L,n)         ((CallInfo *)((char *)L->base_ci + (n)))
+
+
+/* results from luaD_precall */
+#define PCRLUA         0       /* initiated a call to a Lua function */
+#define PCRC           1       /* did a call to a C function */
+#define PCRYIELD       2       /* C funtion yielded */
+
+
+/* type of protected functions, to be ran by `runprotected' */
+typedef void (*Pfunc) (lua_State *L, void *ud);
+
+LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name);
+LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line);
+LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults);
+LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
+LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
+                                        ptrdiff_t oldtop, ptrdiff_t ef);
+LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult);
+LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize);
+LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
+LUAI_FUNC void luaD_growstack (lua_State *L, int n);
+
+LUAI_FUNC void luaD_throw (lua_State *L, int errcode);
+LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
+
+LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop);
+
+#endif
+
diff --git a/src/binlibs/pluto/pdep/lfunc.h b/src/binlibs/pluto/pdep/lfunc.h
new file mode 100644 (file)
index 0000000..a68cf51
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $
+** Auxiliary functions to manipulate prototypes and closures
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lfunc_h
+#define lfunc_h
+
+
+#include "lobject.h"
+
+
+#define sizeCclosure(n)        (cast(int, sizeof(CClosure)) + \
+                         cast(int, sizeof(TValue)*((n)-1)))
+
+#define sizeLclosure(n)        (cast(int, sizeof(LClosure)) + \
+                         cast(int, sizeof(TValue *)*((n)-1)))
+
+
+LUAI_FUNC Proto *luaF_newproto (lua_State *L);
+LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e);
+LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e);
+LUAI_FUNC UpVal *luaF_newupval (lua_State *L);
+LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
+LUAI_FUNC void luaF_close (lua_State *L, StkId level);
+LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);
+LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c);
+LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv);
+LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,
+                                         int pc);
+
+
+#endif
diff --git a/src/binlibs/pluto/pdep/lgc.h b/src/binlibs/pluto/pdep/lgc.h
new file mode 100644 (file)
index 0000000..5a8dc60
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $
+** Garbage Collector
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lgc_h
+#define lgc_h
+
+
+#include "lobject.h"
+
+
+/*
+** Possible states of the Garbage Collector
+*/
+#define GCSpause       0
+#define GCSpropagate   1
+#define GCSsweepstring 2
+#define GCSsweep       3
+#define GCSfinalize    4
+
+
+/*
+** some userful bit tricks
+*/
+#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m)))
+#define setbits(x,m)   ((x) |= (m))
+#define testbits(x,m)  ((x) & (m))
+#define bitmask(b)     (1<<(b))
+#define bit2mask(b1,b2)        (bitmask(b1) | bitmask(b2))
+#define l_setbit(x,b)  setbits(x, bitmask(b))
+#define resetbit(x,b)  resetbits(x, bitmask(b))
+#define testbit(x,b)   testbits(x, bitmask(b))
+#define set2bits(x,b1,b2)      setbits(x, (bit2mask(b1, b2)))
+#define reset2bits(x,b1,b2)    resetbits(x, (bit2mask(b1, b2)))
+#define test2bits(x,b1,b2)     testbits(x, (bit2mask(b1, b2)))
+
+
+
+/*
+** Layout for bit use in `marked' field:
+** bit 0 - object is white (type 0)
+** bit 1 - object is white (type 1)
+** bit 2 - object is black
+** bit 3 - for userdata: has been finalized
+** bit 3 - for tables: has weak keys
+** bit 4 - for tables: has weak values
+** bit 5 - object is fixed (should not be collected)
+** bit 6 - object is "super" fixed (only the main thread)
+*/
+
+
+#define WHITE0BIT      0
+#define WHITE1BIT      1
+#define BLACKBIT       2
+#define FINALIZEDBIT   3
+#define KEYWEAKBIT     3
+#define VALUEWEAKBIT   4
+#define FIXEDBIT       5
+#define SFIXEDBIT      6
+#define WHITEBITS      bit2mask(WHITE0BIT, WHITE1BIT)
+
+
+#define iswhite(x)      test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
+#define isblack(x)      testbit((x)->gch.marked, BLACKBIT)
+#define isgray(x)      (!isblack(x) && !iswhite(x))
+
+#define otherwhite(g)  (g->currentwhite ^ WHITEBITS)
+#define isdead(g,v)    ((v)->gch.marked & otherwhite(g) & WHITEBITS)
+
+#define changewhite(x) ((x)->gch.marked ^= WHITEBITS)
+#define gray2black(x)  l_setbit((x)->gch.marked, BLACKBIT)
+
+#define valiswhite(x)  (iscollectable(x) && iswhite(gcvalue(x)))
+
+#define luaC_white(g)  cast(lu_byte, (g)->currentwhite & WHITEBITS)
+
+
+#define luaC_checkGC(L) { \
+  condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \
+  if (G(L)->totalbytes >= G(L)->GCthreshold) \
+       luaC_step(L); }
+
+
+#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p)))  \
+       luaC_barrierf(L,obj2gco(p),gcvalue(v)); }
+
+#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t)))  \
+       luaC_barrierback(L,t); }
+
+#define luaC_objbarrier(L,p,o)  \
+       { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \
+               luaC_barrierf(L,obj2gco(p),obj2gco(o)); }
+
+#define luaC_objbarriert(L,t,o)  \
+   { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); }
+
+LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all);
+LUAI_FUNC void luaC_callGCTM (lua_State *L);
+LUAI_FUNC void luaC_freeall (lua_State *L);
+LUAI_FUNC void luaC_step (lua_State *L);
+LUAI_FUNC void luaC_fullgc (lua_State *L);
+LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt);
+LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv);
+LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v);
+LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t);
+
+
+#endif
diff --git a/src/binlibs/pluto/pdep/llimits.h b/src/binlibs/pluto/pdep/llimits.h
new file mode 100644 (file)
index 0000000..ca8dcb7
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $
+** Limits, basic types, and some other `installation-dependent' definitions
+** See Copyright Notice in lua.h
+*/
+
+#ifndef llimits_h
+#define llimits_h
+
+
+#include <limits.h>
+#include <stddef.h>
+
+
+#include "lua.h"
+
+
+typedef LUAI_UINT32 lu_int32;
+
+typedef LUAI_UMEM lu_mem;
+
+typedef LUAI_MEM l_mem;
+
+
+
+/* chars used as small naturals (so that `char' is reserved for characters) */
+typedef unsigned char lu_byte;
+
+
+#define MAX_SIZET      ((size_t)(~(size_t)0)-2)
+
+#define MAX_LUMEM      ((lu_mem)(~(lu_mem)0)-2)
+
+
+#define MAX_INT (INT_MAX-2)  /* maximum value of an int (-2 for safety) */
+
+/*
+** conversion of pointer to integer
+** this is for hashing only; there is no problem if the integer
+** cannot hold the whole pointer value
+*/
+#define IntPoint(p)  ((unsigned int)(lu_mem)(p))
+
+
+
+/* type to ensure maximum alignment */
+typedef LUAI_USER_ALIGNMENT_T L_Umaxalign;
+
+
+/* result of a `usual argument conversion' over lua_Number */
+typedef LUAI_UACNUMBER l_uacNumber;
+
+
+/* internal assertions for in-house debugging */
+#ifdef lua_assert
+
+#define check_exp(c,e)         (lua_assert(c), (e))
+#define api_check(l,e)         lua_assert(e)
+
+#else
+
+#define lua_assert(c)          ((void)0)
+#define check_exp(c,e)         (e)
+#define api_check              luai_apicheck
+
+#endif
+
+
+#ifndef UNUSED
+#define UNUSED(x)      ((void)(x))     /* to avoid warnings */
+#endif
+
+
+#ifndef cast
+#define cast(t, exp)   ((t)(exp))
+#endif
+
+#define cast_byte(i)   cast(lu_byte, (i))
+#define cast_num(i)    cast(lua_Number, (i))
+#define cast_int(i)    cast(int, (i))
+
+
+
+/*
+** type for virtual-machine instructions
+** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
+*/
+typedef lu_int32 Instruction;
+
+
+
+/* maximum stack for a Lua function */
+#define MAXSTACK       250
+
+
+
+/* minimum size for the string table (must be power of 2) */
+#ifndef MINSTRTABSIZE
+#define MINSTRTABSIZE  32
+#endif
+
+
+/* minimum size for string buffer */
+#ifndef LUA_MINBUFFER
+#define LUA_MINBUFFER  32
+#endif
+
+
+#ifndef lua_lock
+#define lua_lock(L)     ((void) 0) 
+#define lua_unlock(L)   ((void) 0)
+#endif
+
+#ifndef luai_threadyield
+#define luai_threadyield(L)     {lua_unlock(L); lua_lock(L);}
+#endif
+
+
+/*
+** macro to control inclusion of some hard tests on stack reallocation
+*/ 
+#ifndef HARDSTACKTESTS
+#define condhardstacktests(x)  ((void)0)
+#else
+#define condhardstacktests(x)  x
+#endif
+
+#endif
diff --git a/src/binlibs/pluto/pdep/lobject.h b/src/binlibs/pluto/pdep/lobject.h
new file mode 100644 (file)
index 0000000..e7199df
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+** $Id: lobject.h,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $
+** Type definitions for Lua objects
+** See Copyright Notice in lua.h
+*/
+
+
+#ifndef lobject_h
+#define lobject_h
+
+
+#include <stdarg.h>
+
+
+#include "llimits.h"
+#include "lua.h"
+
+
+/* tags for values visible from Lua */
+#define LAST_TAG       LUA_TTHREAD
+
+#define NUM_TAGS       (LAST_TAG+1)
+
+
+/*
+** Extra tags for non-values
+*/
+#define LUA_TPROTO     (LAST_TAG+1)
+#define LUA_TUPVAL     (LAST_TAG+2)
+#define LUA_TDEADKEY   (LAST_TAG+3)
+
+
+/*
+** Union of all collectable objects
+*/
+typedef union GCObject GCObject;
+
+
+/*
+** Common Header for all collectable objects (in macro form, to be
+** included in other objects)
+*/
+#define CommonHeader   GCObject *next; lu_byte tt; lu_byte marked
+
+
+/*
+** Common header in struct form
+*/
+typedef struct GCheader {
+  CommonHeader;
+} GCheader;
+
+
+
+
+/*
+** Union of all Lua values
+*/
+typedef union {
+  GCObject *gc;
+  void *p;
+  lua_Number n;
+  int b;
+} Value;
+
+
+/*
+** Tagged Values
+*/
+
+#define TValuefields   Value value; int tt
+
+typedef struct lua_TValue {
+  TValuefields;
+} TValue;
+
+
+/* Macros to test type */
+#define ttisnil(o)     (ttype(o) == LUA_TNIL)
+#define ttisnumber(o)  (ttype(o) == LUA_TNUMBER)
+#define ttisstring(o)  (ttype(o) == LUA_TSTRING)
+#define ttistable(o)   (ttype(o) == LUA_TTABLE)
+#define ttisfunction(o)        (ttype(o) == LUA_TFUNCTION)
+#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN)
+#define ttisuserdata(o)        (ttype(o) == LUA_TUSERDATA)
+#define ttisthread(o)  (ttype(o) == LUA_TTHREAD)
+#define ttislightuserdata(o)   (ttype(o) == LUA_TLIGHTUSERDATA)
+
+/* Macros to access values */
+#define ttype(o)       ((o)->tt)
+#define gcvalue(o)     check_exp(iscollectable(o), (o)->value.gc)
+#define pvalue(o)      check_exp(ttislightuserdata(o), (o)->value.p)
+#define nvalue(o)      check_exp(ttisnumber(o), (o)->value.n)
+#define rawtsvalue(o)  check_exp(ttisstring(o), &(o)->value.gc->ts)
+#define tsvalue(o)     (&rawtsvalue(o)->tsv)
+#define rawuvalue(o)   check_exp(ttisuserdata(o), &(o)->value.gc->u)
+#define uvalue(o)      (&rawuvalue(o)->uv)
+#define clvalue(o)     check_exp(ttisfunction(o), &(o)->value.gc->cl)
+#define hvalue(o)      check_exp(ttistable(o), &(o)->value.gc->h)
+#define bvalue(o)      check_exp(ttisboolean(o), (o)->value.b)
+#define thvalue(o)     check_exp(ttisthread(o), &(o)->value.gc->th)
+
+#define l_isfalse(o)   (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))
+
+/*
+** for internal debug only
+*/
+#define checkconsistency(obj) \
+  lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt))
+
+#define checkliveness(g,obj) \
+  lua_assert(!iscollectable(obj) || \
+  ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc)))
+
+
+/* Macros to set values */
+#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
+
+#define setnvalue(obj,x) \
+  { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; }
+
+#define setpvalue(obj,x) \
+  { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; }
+
+#define setbvalue(obj,x) \
+  { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; }
+
+#define setsvalue(L,obj,x) \
+  { TValue *i_o=(obj); \
+    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \
+    checkliveness(G(L),i_o); }
+
+#define setuvalue(L,obj,x) \
+  { TValue *i_o=(obj); \
+    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \
+    checkliveness(G(L),i_o); }
+
+#define setthvalue(L,obj,x) \
+  { TValue *i_o=(obj); \
+    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \
+    checkliveness(G(L),i_o); }
+
+#define setclvalue(L,obj,x) \
+  { TValue *i_o=(obj); \
+    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \
+    checkliveness(G(L),i_o); }
+
+#define sethvalue(L,obj,x) \
+  { TValue *i_o=(obj); \
+    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \
+    checkliveness(G(L),i_o); }
+
+#define setptvalue(L,obj,x) \
+  { TValue *i_o=(obj); \
+    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \
+    checkliveness(G(L),i_o); }
+
+
+
+
+#define setobj(L,obj1,obj2) \
+  { const TValue *o2=(obj2); TValue *o1=(obj1); \
+    o1->value = o2->value; o1->tt=o2->tt; \
+    checkliveness(G(L),o1); }
+
+
+/*
+** different types of sets, according to destination
+*/
+
+/* from stack to (same) stack */
+#define setobjs2s      setobj
+/* to stack (not from same stack) */
+#define setobj2s       setobj
+#define setsvalue2s    setsvalue
+#define sethvalue2s    sethvalue
+#define setptvalue2s   setptvalue
+/* from table to same table */
+#define setobjt2t      setobj
+/* to table */
+#define setobj2t       setobj
+/* to new object */
+#define setobj2n       setobj
+#define setsvalue2n    setsvalue
+
+#define setttype(obj, tt) (ttype(obj) = (tt))
+
+
+#define iscollectable(o)       (ttype(o) >= LUA_TSTRING)
+
+
+
+typedef TValue *StkId;  /* index to stack elements */
+
+
+/*
+** String headers for string table
+*/
+typedef union TString {
+  L_Umaxalign dummy;  /* ensures maximum alignment for strings */
+  struct {
+    CommonHeader;
+    lu_byte reserved;
+    unsigned int hash;
+    size_t len;
+  } tsv;
+} TString;
+
+
+#define getstr(ts)     cast(const char *, (ts) + 1)
+#define svalue(o)       getstr(tsvalue(o))
+
+
+
+typedef union Udata {
+  L_Umaxalign dummy;  /* ensures maximum alignment for `local' udata */
+  struct {
+    CommonHeader;
+    struct Table *metatable;
+    struct Table *env;
+    size_t len;
+  } uv;
+} Udata;
+
+
+
+
+/*
+** Function Prototypes
+*/
+typedef struct Proto {
+  CommonHeader;
+  TValue *k;  /* constants used by the function */
+  Instruction *code;
+  struct Proto **p;  /* functions defined inside the function */
+  int *lineinfo;  /* map from opcodes to source lines */
+  struct LocVar *locvars;  /* information about local variables */
+  TString **upvalues;  /* upvalue names */
+  TString  *source;
+  int sizeupvalues;
+  int sizek;  /* size of `k' */
+  int sizecode;
+  int sizelineinfo;
+  int sizep;  /* size of `p' */
+  int sizelocvars;
+  int linedefined;
+  int lastlinedefined;
+  GCObject *gclist;
+  lu_byte nups;  /* number of upvalues */
+  lu_byte numparams;
+  lu_byte is_vararg;
+  lu_byte maxstacksize;
+} Proto;
+
+
+/* masks for new-style vararg */
+#define VARARG_HASARG          1
+#define VARARG_ISVARARG                2
+#define VARARG_NEEDSARG                4
+
+
+typedef struct LocVar {
+  TString *varname;
+  int startpc;  /* first point where variable is active */
+  int endpc;    /* first point where variable is dead */
+} LocVar;
+
+
+
+/*
+** Upvalues
+*/
+
+typedef struct UpVal {
+  CommonHeader;
+  TValue *v;  /* points to stack or to its own value */
+  union {
+    TValue value;  /* the value (when closed) */
+    struct {  /* double linked list (when open) */
+      struct UpVal *prev;
+      struct UpVal *next;
+    } l;
+  } u;
+} UpVal;
+
+
+/*
+** Closures
+*/
+
+#define ClosureHeader \
+       CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \
+       struct Table *env
+
+typedef struct CClosure {
+  ClosureHeader;
+  lua_CFunction f;
+  TValue upvalue[1];
+} CClosure;
+
+
+typedef struct LClosure {
+  ClosureHeader;
+  struct Proto *p;
+  UpVal *upvals[1];
+} LClosure;
+
+
+typedef union Closure {
+  CClosure c;
+  LClosure l;
+} Closure;
+
+
+#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC)
+#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC)
+
+
+/*
+** Tables
+*/
+
+typedef union TKey {
+  struct {
+    TValuefields;
+    struct Node *next;  /* for chaining */
+  } nk;
+  TValue tvk;
+} TKey;
+
+
+typedef struct Node {
+  TValue i_val;
+  TKey i_key;
+} Node;
+
+
+typedef struct Table {
+  CommonHeader;
+  lu_byte flags;  /* 1<<p means tagmethod(p) is not present */ 
+  lu_byte lsizenode;  /* log2 of size of `node' array */
+  struct Table *metatable;
+  TValue *array;  /* array part */
+  Node *node;
+  Node *lastfree;  /* any free position is before this position */
+  GCObject *gclist;
+  int sizearray;  /* size of `array' array */
+} Table;
+
+
+
+/*
+** `module' operation for hashing (size is always a power of 2)
+*/
+#define lmod(s,size) \
+       (check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1)))))
+
+
+#define twoto(x)       (1<<(x))
+#define sizenode(t)    (twoto((t)->lsizenode))
+
+
+#define luaO_nilobject         (&luaO_nilobject_)
+
+LUAI_DATA const TValue luaO_nilobject_;
+
+#define ceillog2(x)    (luaO_log2((x)-1) + 1)
+
+LUAI_FUNC int luaO_log2 (unsigned int x);
+LUAI_FUNC int luaO_int2fb (unsigned int x);
+LUAI_FUNC int luaO_fb2int (int x);
+LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2);
+LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result);
+LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
+                                                       va_list argp);
+LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
+LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len);
+
+
+#endif
+
diff --git a/src/binlibs/pluto/pdep/lopcodes.h b/src/binlibs/pluto/pdep/lopcodes.h
new file mode 100644 (file)
index 0000000..41224d6
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $
+** Opcodes for Lua virtual machine
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lopcodes_h
+#define lopcodes_h
+
+#include "llimits.h"
+
+
+/*===========================================================================
+  We assume that instructions are unsigned numbers.
+  All instructions have an opcode in the first 6 bits.
+  Instructions can have the following fields:
+       `A' : 8 bits
+       `B' : 9 bits
+       `C' : 9 bits
+       `Bx' : 18 bits (`B' and `C' together)
+       `sBx' : signed Bx
+
+  A signed argument is represented in excess K; that is, the number
+  value is the unsigned value minus K. K is exactly the maximum value
+  for that argument (so that -max is represented by 0, and +max is
+  represented by 2*max), which is half the maximum for the corresponding
+  unsigned argument.
+===========================================================================*/
+
+
+enum OpMode {iABC, iABx, iAsBx};  /* basic instruction format */
+
+
+/*
+** size and position of opcode arguments.
+*/
+#define SIZE_C         9
+#define SIZE_B         9
+#define SIZE_Bx                (SIZE_C + SIZE_B)
+#define SIZE_A         8
+
+#define SIZE_OP                6
+
+#define POS_OP         0
+#define POS_A          (POS_OP + SIZE_OP)
+#define POS_C          (POS_A + SIZE_A)
+#define POS_B          (POS_C + SIZE_C)
+#define POS_Bx         POS_C
+
+
+/*
+** limits for opcode arguments.
+** we use (signed) int to manipulate most arguments,
+** so they must fit in LUAI_BITSINT-1 bits (-1 for sign)
+*/
+#if SIZE_Bx < LUAI_BITSINT-1
+#define MAXARG_Bx        ((1<<SIZE_Bx)-1)
+#define MAXARG_sBx        (MAXARG_Bx>>1)         /* `sBx' is signed */
+#else
+#define MAXARG_Bx        MAX_INT
+#define MAXARG_sBx        MAX_INT
+#endif
+
+
+#define MAXARG_A        ((1<<SIZE_A)-1)
+#define MAXARG_B        ((1<<SIZE_B)-1)
+#define MAXARG_C        ((1<<SIZE_C)-1)
+
+
+/* creates a mask with `n' 1 bits at position `p' */
+#define MASK1(n,p)     ((~((~(Instruction)0)<<n))<<p)
+
+/* creates a mask with `n' 0 bits at position `p' */
+#define MASK0(n,p)     (~MASK1(n,p))
+
+/*
+** the following macros help to manipulate instructions
+*/
+
+#define GET_OPCODE(i)  (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0)))
+#define SET_OPCODE(i,o)        ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \
+               ((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP))))
+
+#define GETARG_A(i)    (cast(int, ((i)>>POS_A) & MASK1(SIZE_A,0)))
+#define SETARG_A(i,u)  ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \
+               ((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A))))
+
+#define GETARG_B(i)    (cast(int, ((i)>>POS_B) & MASK1(SIZE_B,0)))
+#define SETARG_B(i,b)  ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \
+               ((cast(Instruction, b)<<POS_B)&MASK1(SIZE_B,POS_B))))
+
+#define GETARG_C(i)    (cast(int, ((i)>>POS_C) & MASK1(SIZE_C,0)))
+#define SETARG_C(i,b)  ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \
+               ((cast(Instruction, b)<<POS_C)&MASK1(SIZE_C,POS_C))))
+
+#define GETARG_Bx(i)   (cast(int, ((i)>>POS_Bx) & MASK1(SIZE_Bx,0)))
+#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \
+               ((cast(Instruction, b)<<POS_Bx)&MASK1(SIZE_Bx,POS_Bx))))
+
+#define GETARG_sBx(i)  (GETARG_Bx(i)-MAXARG_sBx)
+#define SETARG_sBx(i,b)        SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx))
+
+
+#define CREATE_ABC(o,a,b,c)    ((cast(Instruction, o)<<POS_OP) \
+                       | (cast(Instruction, a)<<POS_A) \
+                       | (cast(Instruction, b)<<POS_B) \
+                       | (cast(Instruction, c)<<POS_C))
+
+#define CREATE_ABx(o,a,bc)     ((cast(Instruction, o)<<POS_OP) \
+                       | (cast(Instruction, a)<<POS_A) \
+                       | (cast(Instruction, bc)<<POS_Bx))
+
+
+/*
+** Macros to operate RK indices
+*/
+
+/* this bit 1 means constant (0 means register) */
+#define BITRK          (1 << (SIZE_B - 1))
+
+/* test whether value is a constant */
+#define ISK(x)         ((x) & BITRK)
+
+/* gets the index of the constant */
+#define INDEXK(r)      ((int)(r) & ~BITRK)
+
+#define MAXINDEXRK     (BITRK - 1)
+
+/* code a constant index as a RK value */
+#define RKASK(x)       ((x) | BITRK)
+
+
+/*
+** invalid register that fits in 8 bits
+*/
+#define NO_REG         MAXARG_A
+
+
+/*
+** R(x) - register
+** Kst(x) - constant (in constant table)
+** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
+*/
+
+
+/*
+** grep "ORDER OP" if you change these enums
+*/
+
+typedef enum {
+/*----------------------------------------------------------------------
+name           args    description
+------------------------------------------------------------------------*/
+OP_MOVE,/*     A B     R(A) := R(B)                                    */
+OP_LOADK,/*    A Bx    R(A) := Kst(Bx)                                 */
+OP_LOADBOOL,/* A B C   R(A) := (Bool)B; if (C) pc++                    */
+OP_LOADNIL,/*  A B     R(A) := ... := R(B) := nil                      */
+OP_GETUPVAL,/* A B     R(A) := UpValue[B]                              */
+
+OP_GETGLOBAL,/*        A Bx    R(A) := Gbl[Kst(Bx)]                            */
+OP_GETTABLE,/* A B C   R(A) := R(B)[RK(C)]                             */
+
+OP_SETGLOBAL,/*        A Bx    Gbl[Kst(Bx)] := R(A)                            */
+OP_SETUPVAL,/* A B     UpValue[B] := R(A)                              */
+OP_SETTABLE,/* A B C   R(A)[RK(B)] := RK(C)                            */
+
+OP_NEWTABLE,/* A B C   R(A) := {} (size = B,C)                         */
+
+OP_SELF,/*     A B C   R(A+1) := R(B); R(A) := R(B)[RK(C)]             */
+
+OP_ADD,/*      A B C   R(A) := RK(B) + RK(C)                           */
+OP_SUB,/*      A B C   R(A) := RK(B) - RK(C)                           */
+OP_MUL,/*      A B C   R(A) := RK(B) * RK(C)                           */
+OP_DIV,/*      A B C   R(A) := RK(B) / RK(C)                           */
+OP_MOD,/*      A B C   R(A) := RK(B) % RK(C)                           */
+OP_POW,/*      A B C   R(A) := RK(B) ^ RK(C)                           */
+OP_UNM,/*      A B     R(A) := -R(B)                                   */
+OP_NOT,/*      A B     R(A) := not R(B)                                */
+OP_LEN,/*      A B     R(A) := length of R(B)                          */
+
+OP_CONCAT,/*   A B C   R(A) := R(B).. ... ..R(C)                       */
+
+OP_JMP,/*      sBx     pc+=sBx                                 */
+
+OP_EQ,/*       A B C   if ((RK(B) == RK(C)) ~= A) then pc++            */
+OP_LT,/*       A B C   if ((RK(B) <  RK(C)) ~= A) then pc++            */
+OP_LE,/*       A B C   if ((RK(B) <= RK(C)) ~= A) then pc++            */
+
+OP_TEST,/*     A C     if not (R(A) <=> C) then pc++                   */ 
+OP_TESTSET,/*  A B C   if (R(B) <=> C) then R(A) := R(B) else pc++     */ 
+
+OP_CALL,/*     A B C   R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
+OP_TAILCALL,/* A B C   return R(A)(R(A+1), ... ,R(A+B-1))              */
+OP_RETURN,/*   A B     return R(A), ... ,R(A+B-2)      (see note)      */
+
+OP_FORLOOP,/*  A sBx   R(A)+=R(A+2);
+                       if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
+OP_FORPREP,/*  A sBx   R(A)-=R(A+2); pc+=sBx                           */
+
+OP_TFORLOOP,/* A C     R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); 
+                        if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++  */ 
+OP_SETLIST,/*  A B C   R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B        */
+
+OP_CLOSE,/*    A       close all variables in the stack up to (>=) R(A)*/
+OP_CLOSURE,/*  A Bx    R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n))  */
+
+OP_VARARG/*    A B     R(A), R(A+1), ..., R(A+B-1) = vararg            */
+} OpCode;
+
+
+#define NUM_OPCODES    (cast(int, OP_VARARG) + 1)
+
+
+
+/*===========================================================================
+  Notes:
+  (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
+      and can be 0: OP_CALL then sets `top' to last_result+1, so
+      next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'.
+
+  (*) In OP_VARARG, if (B == 0) then use actual number of varargs and
+      set top (like in OP_CALL with C == 0).
+
+  (*) In OP_RETURN, if (B == 0) then return up to `top'
+
+  (*) In OP_SETLIST, if (B == 0) then B = `top';
+      if (C == 0) then next `instruction' is real C
+
+  (*) For comparisons, A specifies what condition the test should accept
+      (true or false).
+
+  (*) All `skips' (pc++) assume that next instruction is a jump
+===========================================================================*/
+
+
+/*
+** masks for instruction properties. The format is:
+** bits 0-1: op mode
+** bits 2-3: C arg mode
+** bits 4-5: B arg mode
+** bit 6: instruction set register A
+** bit 7: operator is a test
+*/  
+
+enum OpArgMask {
+  OpArgN,  /* argument is not used */
+  OpArgU,  /* argument is used */
+  OpArgR,  /* argument is a register or a jump offset */
+  OpArgK   /* argument is a constant or register/constant */
+};
+
+LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES];
+
+#define getOpMode(m)   (cast(enum OpMode, luaP_opmodes[m] & 3))
+#define getBMode(m)    (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3))
+#define getCMode(m)    (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3))
+#define testAMode(m)   (luaP_opmodes[m] & (1 << 6))
+#define testTMode(m)   (luaP_opmodes[m] & (1 << 7))
+
+
+LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1];  /* opcode names */
+
+
+/* number of list items to accumulate before a SETLIST instruction */
+#define LFIELDS_PER_FLUSH      50
+
+
+#endif
diff --git a/src/binlibs/pluto/pdep/lstate.h b/src/binlibs/pluto/pdep/lstate.h
new file mode 100644 (file)
index 0000000..3bc575b
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $
+** Global State
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lstate_h
+#define lstate_h
+
+#include "lua.h"
+
+#include "lobject.h"
+#include "ltm.h"
+#include "lzio.h"
+
+
+
+struct lua_longjmp;  /* defined in ldo.c */
+
+
+/* table of globals */
+#define gt(L)  (&L->l_gt)
+
+/* registry */
+#define registry(L)    (&G(L)->l_registry)
+
+
+/* extra stack space to handle TM calls and some other extras */
+#define EXTRA_STACK   5
+
+
+#define BASIC_CI_SIZE           8
+
+#define BASIC_STACK_SIZE        (2*LUA_MINSTACK)
+
+
+
+typedef struct stringtable {
+  GCObject **hash;
+  lu_int32 nuse;  /* number of elements */
+  int size;
+} stringtable;
+
+
+/*
+** informations about a call
+*/
+typedef struct CallInfo {
+  StkId base;  /* base for this function */
+  StkId func;  /* function index in the stack */
+  StkId        top;  /* top for this function */
+  const Instruction *savedpc;
+  int nresults;  /* expected number of results from this function */
+  int tailcalls;  /* number of tail calls lost under this entry */
+} CallInfo;
+
+
+
+#define curr_func(L)   (clvalue(L->ci->func))
+#define ci_func(ci)    (clvalue((ci)->func))
+#define f_isLua(ci)    (!ci_func(ci)->c.isC)
+#define isLua(ci)      (ttisfunction((ci)->func) && f_isLua(ci))
+
+
+/*
+** `global state', shared by all threads of this state
+*/
+typedef struct global_State {
+  stringtable strt;  /* hash table for strings */
+  lua_Alloc frealloc;  /* function to reallocate memory */
+  void *ud;         /* auxiliary data to `frealloc' */
+  lu_byte currentwhite;
+  lu_byte gcstate;  /* state of garbage collector */
+  int sweepstrgc;  /* position of sweep in `strt' */
+  GCObject *rootgc;  /* list of all collectable objects */
+  GCObject **sweepgc;  /* position of sweep in `rootgc' */
+  GCObject *gray;  /* list of gray objects */
+  GCObject *grayagain;  /* list of objects to be traversed atomically */
+  GCObject *weak;  /* list of weak tables (to be cleared) */
+  GCObject *tmudata;  /* last element of list of userdata to be GC */
+  Mbuffer buff;  /* temporary buffer for string concatentation */
+  lu_mem GCthreshold;
+  lu_mem totalbytes;  /* number of bytes currently allocated */
+  lu_mem estimate;  /* an estimate of number of bytes actually in use */
+  lu_mem gcdept;  /* how much GC is `behind schedule' */
+  int gcpause;  /* size of pause between successive GCs */
+  int gcstepmul;  /* GC `granularity' */
+  lua_CFunction panic;  /* to be called in unprotected errors */
+  TValue l_registry;
+  struct lua_State *mainthread;
+  UpVal uvhead;  /* head of double-linked list of all open upvalues */
+  struct Table *mt[NUM_TAGS];  /* metatables for basic types */
+  TString *tmname[TM_N];  /* array with tag-method names */
+} global_State;
+
+
+/*
+** `per thread' state
+*/
+struct lua_State {
+  CommonHeader;
+  lu_byte status;
+  StkId top;  /* first free slot in the stack */
+  StkId base;  /* base of current function */
+  global_State *l_G;
+  CallInfo *ci;  /* call info for current function */
+  const Instruction *savedpc;  /* `savedpc' of current function */
+  StkId stack_last;  /* last free slot in the stack */
+  StkId stack;  /* stack base */
+  CallInfo *end_ci;  /* points after end of ci array*/
+  CallInfo *base_ci;  /* array of CallInfo's */
+  int stacksize;
+  int size_ci;  /* size of array `base_ci' */
+  unsigned short nCcalls;  /* number of nested C calls */
+  unsigned short baseCcalls;  /* nested C calls when resuming coroutine */
+  lu_byte hookmask;
+  lu_byte allowhook;
+  int basehookcount;
+  int hookcount;
+  lua_Hook hook;
+  TValue l_gt;  /* table of globals */
+  TValue env;  /* temporary place for environments */
+  GCObject *openupval;  /* list of open upvalues in this stack */
+  GCObject *gclist;
+  struct lua_longjmp *errorJmp;  /* current error recover point */
+  ptrdiff_t errfunc;  /* current error handling function (stack index) */
+};
+
+
+#define G(L)   (L->l_G)
+
+
+/*
+** Union of all collectable objects
+*/
+union GCObject {
+  GCheader gch;
+  union TString ts;
+  union Udata u;
+  union Closure cl;
+  struct Table h;
+  struct Proto p;
+  struct UpVal uv;
+  struct lua_State th;  /* thread */
+};
+
+
+/* macros to convert a GCObject into a specific value */
+#define rawgco2ts(o)   check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts))
+#define gco2ts(o)      (&rawgco2ts(o)->tsv)
+#define rawgco2u(o)    check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))
+#define gco2u(o)       (&rawgco2u(o)->uv)
+#define gco2cl(o)      check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl))
+#define gco2h(o)       check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))
+#define gco2p(o)       check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))
+#define gco2uv(o)      check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))
+#define ngcotouv(o) \
+       check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv))
+#define gco2th(o)      check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))
+
+/* macro to convert any Lua object into a GCObject */
+#define obj2gco(v)     (cast(GCObject *, (v)))
+
+
+LUAI_FUNC lua_State *luaE_newthread (lua_State *L);
+LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
+
+#endif
+
diff --git a/src/binlibs/pluto/pdep/lstring.h b/src/binlibs/pluto/pdep/lstring.h
new file mode 100644 (file)
index 0000000..73a2ff8
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $
+** String table (keep all strings handled by Lua)
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lstring_h
+#define lstring_h
+
+
+#include "lgc.h"
+#include "lobject.h"
+#include "lstate.h"
+
+
+#define sizestring(s)  (sizeof(union TString)+((s)->len+1)*sizeof(char))
+
+#define sizeudata(u)   (sizeof(union Udata)+(u)->len)
+
+#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s)))
+#define luaS_newliteral(L, s)  (luaS_newlstr(L, "" s, \
+                                 (sizeof(s)/sizeof(char))-1))
+
+#define luaS_fix(s)    l_setbit((s)->tsv.marked, FIXEDBIT)
+
+LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
+LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);
+LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
+
+
+#endif
diff --git a/src/binlibs/pluto/pdep/ltm.h b/src/binlibs/pluto/pdep/ltm.h
new file mode 100644 (file)
index 0000000..64343b7
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $
+** Tag methods
+** See Copyright Notice in lua.h
+*/
+
+#ifndef ltm_h
+#define ltm_h
+
+
+#include "lobject.h"
+
+
+/*
+* WARNING: if you change the order of this enumeration,
+* grep "ORDER TM"
+*/
+typedef enum {
+  TM_INDEX,
+  TM_NEWINDEX,
+  TM_GC,
+  TM_MODE,
+  TM_EQ,  /* last tag method with `fast' access */
+  TM_ADD,
+  TM_SUB,
+  TM_MUL,
+  TM_DIV,
+  TM_MOD,
+  TM_POW,
+  TM_UNM,
+  TM_LEN,
+  TM_LT,
+  TM_LE,
+  TM_CONCAT,
+  TM_CALL,
+  TM_N         /* number of elements in the enum */
+} TMS;
+
+
+
+#define gfasttm(g,et,e) ((et) == NULL ? NULL : \
+  ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))
+
+#define fasttm(l,et,e) gfasttm(G(l), et, e)
+
+LUAI_DATA const char *const luaT_typenames[];
+
+
+LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename);
+LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o,
+                                                       TMS event);
+LUAI_FUNC void luaT_init (lua_State *L);
+
+#endif
diff --git a/src/binlibs/pluto/pdep/lua.h b/src/binlibs/pluto/pdep/lua.h
new file mode 100644 (file)
index 0000000..5bc97b7
--- /dev/null
@@ -0,0 +1,388 @@
+/*
+** $Id: lua.h,v 1.218.1.4 2008/01/03 15:41:15 roberto Exp $
+** Lua - An Extensible Extension Language
+** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
+** See Copyright Notice at the end of this file
+*/
+
+
+#ifndef lua_h
+#define lua_h
+
+#include <stdarg.h>
+#include <stddef.h>
+
+
+#include "luaconf.h"
+
+
+#define LUA_VERSION    "Lua 5.1"
+#define LUA_RELEASE    "Lua 5.1.3"
+#define LUA_VERSION_NUM        501
+#define LUA_COPYRIGHT  "Copyright (C) 1994-2008 Lua.org, PUC-Rio"
+#define LUA_AUTHORS    "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
+
+
+/* mark for precompiled code (`<esc>Lua') */
+#define        LUA_SIGNATURE   "\033Lua"
+
+/* option for multiple returns in `lua_pcall' and `lua_call' */
+#define LUA_MULTRET    (-1)
+
+
+/*
+** pseudo-indices
+*/
+#define LUA_REGISTRYINDEX      (-10000)
+#define LUA_ENVIRONINDEX       (-10001)
+#define LUA_GLOBALSINDEX       (-10002)
+#define lua_upvalueindex(i)    (LUA_GLOBALSINDEX-(i))
+
+
+/* thread status; 0 is OK */
+#define LUA_YIELD      1
+#define LUA_ERRRUN     2
+#define LUA_ERRSYNTAX  3
+#define LUA_ERRMEM     4
+#define LUA_ERRERR     5
+
+
+typedef struct lua_State lua_State;
+
+typedef int (*lua_CFunction) (lua_State *L);
+
+
+/*
+** functions that read/write blocks when loading/dumping Lua chunks
+*/
+typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
+
+typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud);
+
+
+/*
+** prototype for memory-allocation functions
+*/
+typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
+
+
+/*
+** basic types
+*/
+#define LUA_TNONE              (-1)
+
+#define LUA_TNIL               0
+#define LUA_TBOOLEAN           1
+#define LUA_TLIGHTUSERDATA     2
+#define LUA_TNUMBER            3
+#define LUA_TSTRING            4
+#define LUA_TTABLE             5
+#define LUA_TFUNCTION          6
+#define LUA_TUSERDATA          7
+#define LUA_TTHREAD            8
+
+
+
+/* minimum Lua stack available to a C function */
+#define LUA_MINSTACK   20
+
+
+/*
+** generic extra include file
+*/
+#if defined(LUA_USER_H)
+#include LUA_USER_H
+#endif
+
+
+/* type of numbers in Lua */
+typedef LUA_NUMBER lua_Number;
+
+
+/* type for integer functions */
+typedef LUA_INTEGER lua_Integer;
+
+
+
+/*
+** state manipulation
+*/
+LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);
+LUA_API void       (lua_close) (lua_State *L);
+LUA_API lua_State *(lua_newthread) (lua_State *L);
+
+LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
+
+
+/*
+** basic stack manipulation
+*/
+LUA_API int   (lua_gettop) (lua_State *L);
+LUA_API void  (lua_settop) (lua_State *L, int idx);
+LUA_API void  (lua_pushvalue) (lua_State *L, int idx);
+LUA_API void  (lua_remove) (lua_State *L, int idx);
+LUA_API void  (lua_insert) (lua_State *L, int idx);
+LUA_API void  (lua_replace) (lua_State *L, int idx);
+LUA_API int   (lua_checkstack) (lua_State *L, int sz);
+
+LUA_API void  (lua_xmove) (lua_State *from, lua_State *to, int n);
+
+
+/*
+** access functions (stack -> C)
+*/
+
+LUA_API int             (lua_isnumber) (lua_State *L, int idx);
+LUA_API int             (lua_isstring) (lua_State *L, int idx);
+LUA_API int             (lua_iscfunction) (lua_State *L, int idx);
+LUA_API int             (lua_isuserdata) (lua_State *L, int idx);
+LUA_API int             (lua_type) (lua_State *L, int idx);
+LUA_API const char     *(lua_typename) (lua_State *L, int tp);
+
+LUA_API int            (lua_equal) (lua_State *L, int idx1, int idx2);
+LUA_API int            (lua_rawequal) (lua_State *L, int idx1, int idx2);
+LUA_API int            (lua_lessthan) (lua_State *L, int idx1, int idx2);
+
+LUA_API lua_Number      (lua_tonumber) (lua_State *L, int idx);
+LUA_API lua_Integer     (lua_tointeger) (lua_State *L, int idx);
+LUA_API int             (lua_toboolean) (lua_State *L, int idx);
+LUA_API const char     *(lua_tolstring) (lua_State *L, int idx, size_t *len);
+LUA_API size_t          (lua_objlen) (lua_State *L, int idx);
+LUA_API lua_CFunction   (lua_tocfunction) (lua_State *L, int idx);
+LUA_API void          *(lua_touserdata) (lua_State *L, int idx);
+LUA_API lua_State      *(lua_tothread) (lua_State *L, int idx);
+LUA_API const void     *(lua_topointer) (lua_State *L, int idx);
+
+
+/*
+** push functions (C -> stack)
+*/
+LUA_API void  (lua_pushnil) (lua_State *L);
+LUA_API void  (lua_pushnumber) (lua_State *L, lua_Number n);
+LUA_API void  (lua_pushinteger) (lua_State *L, lua_Integer n);
+LUA_API void  (lua_pushlstring) (lua_State *L, const char *s, size_t l);
+LUA_API void  (lua_pushstring) (lua_State *L, const char *s);
+LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
+                                                      va_list argp);
+LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
+LUA_API void  (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
+LUA_API void  (lua_pushboolean) (lua_State *L, int b);
+LUA_API void  (lua_pushlightuserdata) (lua_State *L, void *p);
+LUA_API int   (lua_pushthread) (lua_State *L);
+
+
+/*
+** get functions (Lua -> stack)
+*/
+LUA_API void  (lua_gettable) (lua_State *L, int idx);
+LUA_API void  (lua_getfield) (lua_State *L, int idx, const char *k);
+LUA_API void  (lua_rawget) (lua_State *L, int idx);
+LUA_API void  (lua_rawgeti) (lua_State *L, int idx, int n);
+LUA_API void  (lua_createtable) (lua_State *L, int narr, int nrec);
+LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);
+LUA_API int   (lua_getmetatable) (lua_State *L, int objindex);
+LUA_API void  (lua_getfenv) (lua_State *L, int idx);
+
+
+/*
+** set functions (stack -> Lua)
+*/
+LUA_API void  (lua_settable) (lua_State *L, int idx);
+LUA_API void  (lua_setfield) (lua_State *L, int idx, const char *k);
+LUA_API void  (lua_rawset) (lua_State *L, int idx);
+LUA_API void  (lua_rawseti) (lua_State *L, int idx, int n);
+LUA_API int   (lua_setmetatable) (lua_State *L, int objindex);
+LUA_API int   (lua_setfenv) (lua_State *L, int idx);
+
+
+/*
+** `load' and `call' functions (load and run Lua code)
+*/
+LUA_API void  (lua_call) (lua_State *L, int nargs, int nresults);
+LUA_API int   (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
+LUA_API int   (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud);
+LUA_API int   (lua_load) (lua_State *L, lua_Reader reader, void *dt,
+                                        const char *chunkname);
+
+LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data);
+
+
+/*
+** coroutine functions
+*/
+LUA_API int  (lua_yield) (lua_State *L, int nresults);
+LUA_API int  (lua_resume) (lua_State *L, int narg);
+LUA_API int  (lua_status) (lua_State *L);
+
+/*
+** garbage-collection function and options
+*/
+
+#define LUA_GCSTOP             0
+#define LUA_GCRESTART          1
+#define LUA_GCCOLLECT          2
+#define LUA_GCCOUNT            3
+#define LUA_GCCOUNTB           4
+#define LUA_GCSTEP             5
+#define LUA_GCSETPAUSE         6
+#define LUA_GCSETSTEPMUL       7
+
+LUA_API int (lua_gc) (lua_State *L, int what, int data);
+
+
+/*
+** miscellaneous functions
+*/
+
+LUA_API int   (lua_error) (lua_State *L);
+
+LUA_API int   (lua_next) (lua_State *L, int idx);
+
+LUA_API void  (lua_concat) (lua_State *L, int n);
+
+LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
+LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
+
+
+
+/* 
+** ===============================================================
+** some useful macros
+** ===============================================================
+*/
+
+#define lua_pop(L,n)           lua_settop(L, -(n)-1)
+
+#define lua_newtable(L)                lua_createtable(L, 0, 0)
+
+#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
+
+#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0)
+
+#define lua_strlen(L,i)                lua_objlen(L, (i))
+
+#define lua_isfunction(L,n)    (lua_type(L, (n)) == LUA_TFUNCTION)
+#define lua_istable(L,n)       (lua_type(L, (n)) == LUA_TTABLE)
+#define lua_islightuserdata(L,n)       (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
+#define lua_isnil(L,n)         (lua_type(L, (n)) == LUA_TNIL)
+#define lua_isboolean(L,n)     (lua_type(L, (n)) == LUA_TBOOLEAN)
+#define lua_isthread(L,n)      (lua_type(L, (n)) == LUA_TTHREAD)
+#define lua_isnone(L,n)                (lua_type(L, (n)) == LUA_TNONE)
+#define lua_isnoneornil(L, n)  (lua_type(L, (n)) <= 0)
+
+#define lua_pushliteral(L, s)  \
+       lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
+
+#define lua_setglobal(L,s)     lua_setfield(L, LUA_GLOBALSINDEX, (s))
+#define lua_getglobal(L,s)     lua_getfield(L, LUA_GLOBALSINDEX, (s))
+
+#define lua_tostring(L,i)      lua_tolstring(L, (i), NULL)
+
+
+
+/*
+** compatibility macros and functions
+*/
+
+#define lua_open()     luaL_newstate()
+
+#define lua_getregistry(L)     lua_pushvalue(L, LUA_REGISTRYINDEX)
+
+#define lua_getgccount(L)      lua_gc(L, LUA_GCCOUNT, 0)
+
+#define lua_Chunkreader                lua_Reader
+#define lua_Chunkwriter                lua_Writer
+
+
+/* hack */
+LUA_API void lua_setlevel      (lua_State *from, lua_State *to);
+
+
+/*
+** {======================================================================
+** Debug API
+** =======================================================================
+*/
+
+
+/*
+** Event codes
+*/
+#define LUA_HOOKCALL   0
+#define LUA_HOOKRET    1
+#define LUA_HOOKLINE   2
+#define LUA_HOOKCOUNT  3
+#define LUA_HOOKTAILRET 4
+
+
+/*
+** Event masks
+*/
+#define LUA_MASKCALL   (1 << LUA_HOOKCALL)
+#define LUA_MASKRET    (1 << LUA_HOOKRET)
+#define LUA_MASKLINE   (1 << LUA_HOOKLINE)
+#define LUA_MASKCOUNT  (1 << LUA_HOOKCOUNT)
+
+typedef struct lua_Debug lua_Debug;  /* activation record */
+
+
+/* Functions to be called by the debuger in specific events */
+typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
+
+
+LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar);
+LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
+LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);
+LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);
+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);
+
+LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count);
+LUA_API lua_Hook lua_gethook (lua_State *L);
+LUA_API int lua_gethookmask (lua_State *L);
+LUA_API int lua_gethookcount (lua_State *L);
+
+
+struct lua_Debug {
+  int event;
+  const char *name;    /* (n) */
+  const char *namewhat;        /* (n) `global', `local', `field', `method' */
+  const char *what;    /* (S) `Lua', `C', `main', `tail' */
+  const char *source;  /* (S) */
+  int currentline;     /* (l) */
+  int nups;            /* (u) number of upvalues */
+  int linedefined;     /* (S) */
+  int lastlinedefined; /* (S) */
+  char short_src[LUA_IDSIZE]; /* (S) */
+  /* private part */
+  int i_ci;  /* active function */
+};
+
+/* }====================================================================== */
+
+
+/******************************************************************************
+* Copyright (C) 1994-2008 Lua.org, PUC-Rio.  All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining
+* a copy of this software and associated documentation files (the
+* "Software"), to deal in the Software without restriction, including
+* without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to
+* permit persons to whom the Software is furnished to do so, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+******************************************************************************/
+
+
+#endif
diff --git a/src/binlibs/pluto/pdep/lzio.h b/src/binlibs/pluto/pdep/lzio.h
new file mode 100644 (file)
index 0000000..4e654a5
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $
+** Buffered streams
+** See Copyright Notice in lua.h
+*/
+
+
+#ifndef lzio_h
+#define lzio_h
+
+#include "lua.h"
+
+
+#define EOZ    (-1)                    /* end of stream */
+
+typedef struct Zio ZIO;
+
+#define char2int(c)    cast(int, cast(unsigned char, (c)))
+
+#define zgetc(z)  (((z)->n--)>0 ?  char2int(*(z)->p++) : pdep_fill(z))
+
+typedef struct Mbuffer {
+  char *buffer;
+  size_t n;
+  size_t buffsize;
+} Mbuffer;
+
+#define pdep_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0)
+
+#define pdep_buffer(buff)      ((buff)->buffer)
+#define pdep_sizebuffer(buff)  ((buff)->buffsize)
+#define pdep_bufflen(buff)     ((buff)->n)
+
+#define pdep_resetbuffer(buff) ((buff)->n = 0)
+
+
+#define pdep_resizebuffer(L, buff, size) \
+       (pdep_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \
+       (buff)->buffsize = size)
+
+#define pdep_freebuffer(L, buff)       pdep_resizebuffer(L, buff, 0)
+
+
+LUAI_FUNC char *pdep_openspace (lua_State *L, Mbuffer *buff, size_t n);
+LUAI_FUNC void pdep_init (lua_State *L, ZIO *z, lua_Reader reader,
+                                        void *data);
+LUAI_FUNC size_t pdep_read (ZIO* z, void* b, size_t n);        /* read next n bytes */
+LUAI_FUNC int pdep_lookahead (ZIO *z);
+
+
+
+/* --------- Private Part ------------------ */
+
+struct Zio {
+  size_t n;                    /* bytes still unread */
+  const char *p;               /* current position in buffer */
+  lua_Reader reader;
+  void* data;                  /* additional data */
+  lua_State *L;                        /* Lua state (for reader) */
+};
+
+
+LUAI_FUNC int pdep_fill (ZIO *z);
+
+#endif
diff --git a/src/binlibs/pluto/pdep/pdep.h b/src/binlibs/pluto/pdep/pdep.h
new file mode 100644 (file)
index 0000000..c26f456
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef PDEP_H
+#define PDEP_H
+
+#include "lua.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lgc.h"
+#include "llimits.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "lauxlib.h"
+
+
+#define pdep_reallocv(L,b,on,n,e) \
+       pdep_realloc_(L, (b), (on)*(e), (n)*(e))
+#define pdep_reallocvector(L, v,oldn,n,t) \
+       ((v)=cast(t *, pdep_reallocv(L, v, oldn, n, sizeof(t))))
+#define pdep_freearray(L, b, n, t)   pdep_reallocv(L, (b), n, 0, sizeof(t))
+#define pdep_newvector(L,n,t) \
+       cast(t *, pdep_reallocv(L, NULL, 0, n, sizeof(t)))
+#define pdep_new(L,t)          cast(t *, pdep_malloc(L, sizeof(t)))
+#define pdep_malloc(L,t)       pdep_realloc_(L, NULL, 0, (t))
+#define pdep_checkstack(L,n)   \
+  if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \
+    pdep_growstack(L, n); \
+  else pdep_reallocstack(L, L->stacksize - EXTRA_STACK - 1);
+
+
+void pdep_pushobject (lua_State *L, const TValue *o);
+void *pdep_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize);
+void pdep_link (lua_State *L, GCObject *o, lu_byte tt);
+Proto *pdep_newproto (lua_State *L);
+Closure *pdep_newLclosure (lua_State *L, int nelems, Table *e);
+void pdep_reallocstack (lua_State *L, int newsize);
+void pdep_growstack (lua_State *L, int n);
+void pdep_reallocCI (lua_State *L, int newsize);
+TString *pdep_newlstr (lua_State *L, const char *str, size_t l);
+
+#endif
diff --git a/src/binlibs/pluto/pluto.c b/src/binlibs/pluto/pluto.c
new file mode 100644 (file)
index 0000000..4d3be53
--- /dev/null
@@ -0,0 +1,1536 @@
+/* $Id$ */
+
+/* Pluto - Heavy-duty persistence for Lua
+ * Copyright (C) 2004 by Ben Sunshine-Hill, and released into the public
+ * domain. People making use of this software as part of an application
+ * are politely requested to email the author at sneftel@gmail.com
+ * with a brief description of the application, primarily to satisfy his
+ * curiosity.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "lua.h"
+#include "pluto.h"
+
+#define USE_PDEP
+
+#ifdef USE_PDEP
+#include "pdep/pdep.h"
+#define LIF(prefix, name) pdep ## _ ## name
+#else
+#include "lapi.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lgc.h"
+#include "llimits.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "lauxlib.h"
+#define LIF(prefix, name) lua ## prefix ## _ ## name
+#endif
+
+#include <string.h>
+
+
+
+/* #define PLUTO_DEBUG */
+
+
+
+
+#ifdef PLUTO_DEBUG
+#include <stdio.h>
+#endif
+
+#define PLUTO_TPERMANENT 101
+
+#define verify(x) { int v = (int)((x)); v=v; lua_assert(v); }
+
+typedef struct PersistInfo_t {
+       lua_State *L;
+       int counter;
+       lua_Chunkwriter writer;
+       void *ud;
+#ifdef PLUTO_DEBUG
+       int level;
+#endif
+} PersistInfo;
+
+#ifdef PLUTO_DEBUG
+void printindent(int indent)
+{
+       int il;
+       for(il=0; il<indent; il++) {
+               printf("  ");
+       }
+}
+#endif
+
+/* Mutual recursion requires prototype */
+static void persist(PersistInfo *pi);
+
+/* A simple reimplementation of the unfortunately static function luaA_index.
+ * Does not support the global table, registry, or upvalues. */
+static StkId getobject(lua_State *L, int stackpos)
+{
+       if(stackpos > 0) {
+               lua_assert(L->base+stackpos-1 < L->top);
+               return L->base+stackpos-1;
+       } else {
+               lua_assert(L->top-stackpos >= L->base);
+               return L->top+stackpos;
+       }
+}
+
+/* Choose whether to do a regular or special persistence based on an object's
+ * metatable. "default" is whether the object, if it doesn't have a __persist
+ * entry, is literally persistable or not.
+ * Pushes the unpersist closure and returns true if special persistence is
+ * used. */
+static int persistspecialobject(PersistInfo *pi, int defaction)
+{
+                                       /* perms reftbl ... obj */
+       /* Check whether we should persist literally, or via the __persist
+        * metafunction */
+       if(!lua_getmetatable(pi->L, -1)) {
+               if(defaction) {
+                       {
+                               int zero = 0;
+                               pi->writer(pi->L, &zero, sizeof(int), pi->ud);
+                       }
+                       return 0;
+               } else {
+                       lua_pushstring(pi->L, "Type not literally persistable by default");
+                       lua_error(pi->L);
+               }
+       }
+                                       /* perms reftbl sptbl ... obj mt */
+       lua_pushstring(pi->L, "__persist");
+                                       /* perms reftbl sptbl ... obj mt "__persist" */
+       lua_rawget(pi->L, -2);
+                                       /* perms reftbl sptbl ... obj mt __persist? */
+       if(lua_isnil(pi->L, -1)) {
+                                       /* perms reftbl sptbl ... obj mt nil */
+               lua_pop(pi->L, 2);
+                                       /* perms reftbl sptbl ... obj */
+               if(defaction) {
+                       {
+                               int zero = 0;
+                               pi->writer(pi->L, &zero, sizeof(int), pi->ud);
+                       }
+                       return 0;
+               } else {
+                       lua_pushstring(pi->L, "Type not literally persistable by default");
+                       lua_error(pi->L);
+                       return 0; /* not reached */
+               }
+       } else if(lua_isboolean(pi->L, -1)) {
+                                       /* perms reftbl sptbl ... obj mt bool */
+               if(lua_toboolean(pi->L, -1)) {
+                                       /* perms reftbl sptbl ... obj mt true */
+                       lua_pop(pi->L, 2);
+                                       /* perms reftbl sptbl ... obj */
+                       {
+                               int zero = 0;
+                               pi->writer(pi->L, &zero, sizeof(int), pi->ud);
+                       }
+                       return 0;
+               } else {
+                       lua_pushstring(pi->L, "Metatable forbade persistence");
+                       lua_error(pi->L);
+                       return 0; /* not reached */
+               }
+       } else if(!lua_isfunction(pi->L, -1)) {
+               lua_pushstring(pi->L, "__persist not nil, boolean, or function");
+               lua_error(pi->L);
+       }
+                                       /* perms reftbl ... obj mt __persist */
+       lua_pushvalue(pi->L, -3);
+                                       /* perms reftbl ... obj mt __persist obj */
+#ifdef PLUTO_PASS_USERDATA_TO_PERSIST
+       lua_pushlightuserdata(pi->L, (void*)pi->writer);
+       lua_pushlightuserdata(pi->L, pi->ud);
+                                       /* perms reftbl ... obj mt __persist obj ud */
+       lua_call(pi->L, 3, 1);
+                                       /* perms reftbl ... obj mt func? */
+#else
+       lua_call(pi->L, 1, 1);
+                                       /* perms reftbl ... obj mt func? */
+#endif
+                                       /* perms reftbl ... obj mt func? */
+       if(!lua_isfunction(pi->L, -1)) {
+               lua_pushstring(pi->L, "__persist function did not return a function");
+               lua_error(pi->L);
+       }
+                                       /* perms reftbl ... obj mt func */
+       {
+               int one = 1;
+               pi->writer(pi->L, &one, sizeof(int), pi->ud);
+       }
+       persist(pi);
+                                       /* perms reftbl ... obj mt func */
+       lua_pop(pi->L, 2);
+                                       /* perms reftbl ... obj */
+       return 1;
+}
+
+static void persisttable(PersistInfo *pi)
+{
+                                       /* perms reftbl ... tbl */
+       if(persistspecialobject(pi, 1)) {
+                                       /* perms reftbl ... tbl */
+               return;
+       }
+                                       /* perms reftbl ... tbl */
+       /* First, persist the metatable (if any) */
+       if(!lua_getmetatable(pi->L, -1)) {
+               lua_pushnil(pi->L);
+       }
+                                       /* perms reftbl ... tbl mt/nil */
+       persist(pi);
+       lua_pop(pi->L, 1);
+                                       /* perms reftbl ... tbl */
+
+       /* Now, persist all k/v pairs */
+       lua_pushnil(pi->L);
+                                       /* perms reftbl ... tbl nil */
+       while(lua_next(pi->L, -2)) {
+                                       /* perms reftbl ... tbl k v */
+               lua_pushvalue(pi->L, -2);
+                                       /* perms reftbl ... tbl k v k */
+               persist(pi);
+               lua_pop(pi->L, 1);
+                                       /* perms reftbl ... tbl k v */
+               persist(pi);
+               lua_pop(pi->L, 1);
+                                       /* perms reftbl ... tbl k */
+       }
+                                       /* perms reftbl ... tbl */
+       /* Terminate list */
+       lua_pushnil(pi->L);
+                                       /* perms reftbl ... tbl nil */
+       persist(pi);
+       lua_pop(pi->L, 1);
+                                       /* perms reftbl ... tbl */
+}
+
+static void persistuserdata(PersistInfo *pi) {
+                                       /* perms reftbl ... udata */
+       if(persistspecialobject(pi, 0)) {
+                                       /* perms reftbl ... udata */
+               return;
+       } else {
+       /* Use literal persistence */
+               size_t length = uvalue(getobject(pi->L, -1))->len;
+               pi->writer(pi->L, &length, sizeof(size_t), pi->ud);
+               pi->writer(pi->L, lua_touserdata(pi->L, -1), length, pi->ud);
+               if(!lua_getmetatable(pi->L, -1)) {
+                                       /* perms reftbl ... udata */
+                       lua_pushnil(pi->L);
+                                       /* perms reftbl ... udata mt/nil */
+               }
+               persist(pi);
+               lua_pop(pi->L, 1);
+                                       /* perms reftbl ... udata */
+       }
+}
+
+
+static Proto *toproto(lua_State *L, int stackpos)
+{
+       return gco2p(getobject(L, stackpos)->value.gc);
+}
+
+static UpVal *toupval(lua_State *L, int stackpos)
+{
+       lua_assert(ttype(getobject(L, stackpos)) == LUA_TUPVAL);
+       return gco2uv(getobject(L, stackpos)->value.gc);
+}
+
+static void pushproto(lua_State *L, Proto *proto)
+{
+       TValue o;
+       setptvalue(L, &o, proto);
+       LIF(A,pushobject)(L, &o);
+}
+
+#define setuvvalue(L,obj,x) \
+  { TValue *i_o=(obj); \
+    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUPVAL; \
+    checkliveness(G(L),i_o); }
+
+static void pushupval(lua_State *L, UpVal *upval)
+{
+       TValue o;
+       setuvvalue(L, &o, upval);
+       LIF(A,pushobject)(L, &o);
+}
+
+static void pushclosure(lua_State *L, Closure *closure)
+{
+       TValue o;
+       setclvalue(L, &o, closure);
+       LIF(A,pushobject)(L, &o);
+}
+
+static void persistfunction(PersistInfo *pi)
+{
+                                       /* perms reftbl ... func */
+       Closure *cl = clvalue(getobject(pi->L, -1));
+       if(cl->c.isC) {
+               /* It's a C function. For now, we aren't going to allow
+                * persistence of C closures, even if the "C proto" is
+                * already in the permanents table. */
+               lua_pushstring(pi->L, "Attempt to persist a C function");
+               lua_error(pi->L);
+       } else {
+               /* It's a Lua closure. */
+               {
+                       /* We don't really _NEED_ the number of upvals,
+                        * but it'll simplify things a bit */
+                       pi->writer(pi->L, &cl->l.p->nups, sizeof(lu_byte), pi->ud);
+               }
+               /* Persist prototype */
+               {
+                       pushproto(pi->L, cl->l.p);
+                                       /* perms reftbl ... func proto */
+                       persist(pi);
+                       lua_pop(pi->L, 1);
+                                       /* perms reftbl ... func */
+               }
+               /* Persist upvalue values (not the upvalue objects
+                * themselves) */
+               {
+                       int i;
+                       for(i=0; i<cl->l.p->nups; i++) {
+                                       /* perms reftbl ... func */
+                               pushupval(pi->L, cl->l.upvals[i]);
+                                       /* perms reftbl ... func upval */
+                               persist(pi);
+                               lua_pop(pi->L, 1);
+                                       /* perms reftbl ... func */
+                       }
+                                       /* perms reftbl ... func */
+               }
+               /* Persist function environment */
+               {
+                       lua_getfenv(pi->L, -1);
+                                       /* perms reftbl ... func fenv */
+                       if(lua_equal(pi->L, -1, LUA_GLOBALSINDEX)) {
+                               /* Function has the default fenv */
+                                       /* perms reftbl ... func _G */
+                               lua_pop(pi->L, 1);
+                                       /* perms reftbl ... func */
+                               lua_pushnil(pi->L);
+                                       /* perms reftbl ... func nil */
+                       }
+                                       /* perms reftbl ... func fenv/nil */
+                       persist(pi);
+                       lua_pop(pi->L, 1);
+                                       /* perms reftbl ... func */
+               }
+       }
+}
+
+
+/* Upvalues are tricky. Here's why.
+ *
+ * A particular upvalue may be either "open", in which case its member v
+ * points into a thread's stack, or "closed" in which case it points to the
+ * upvalue itself. An upvalue is closed under any of the following conditions:
+ * -- The function that initially declared the variable "local" returns
+ * -- The thread in which the closure was created is garbage collected
+ *
+ * To make things wackier, just because a thread is reachable by Lua doesn't
+ * mean it's in our root set. We need to be able to treat an open upvalue
+ * from an unreachable thread as a closed upvalue.
+ *
+ * The solution:
+ * (a) For the purposes of persisting, don't indicate whether an upvalue is
+ * closed or not.
+ * (b) When unpersisting, pretend that all upvalues are closed.
+ * (c) When persisting, persist all open upvalues referenced by a thread
+ * that is persisted, and tag each one with the corresponding stack position
+ * (d) When unpersisting, "reopen" each of these upvalues as the thread is
+ * unpersisted
+ */
+static void persistupval(PersistInfo *pi)
+{
+                                       /* perms reftbl ... upval */
+       UpVal *uv = toupval(pi->L, -1);
+
+       /* We can't permit the upval to linger around on the stack, as Lua
+       * will bail if its GC finds it. */
+
+       lua_pop(pi->L, 1);
+                                       /* perms reftbl ... */
+       LIF(A,pushobject)(pi->L, uv->v);
+                                       /* perms reftbl ... obj */
+       persist(pi);
+                                       /* perms reftbl ... obj */
+}
+
+static void persistproto(PersistInfo *pi)
+{
+                                       /* perms reftbl ... proto */
+       Proto *p = toproto(pi->L, -1);
+
+       /* Persist constant refs */
+       {
+               int i;
+               pi->writer(pi->L, &p->sizek, sizeof(int), pi->ud);
+               for(i=0; i<p->sizek; i++) {
+                       LIF(A,pushobject)(pi->L, &p->k[i]);
+                                       /* perms reftbl ... proto const */
+                       persist(pi);
+                       lua_pop(pi->L, 1);
+                                       /* perms reftbl ... proto */
+               }
+       }
+                                       /* perms reftbl ... proto */
+
+       /* serialize inner Proto refs */
+       {
+               int i;
+               pi->writer(pi->L, &p->sizep, sizeof(int), pi->ud);
+               for(i=0; i<p->sizep; i++)
+               {
+                       pushproto(pi->L, p->p[i]);
+                                       /* perms reftbl ... proto subproto */
+                       persist(pi);
+                       lua_pop(pi->L, 1);
+                                       /* perms reftbl ... proto */
+               }
+       }
+                                       /* perms reftbl ... proto */
+       /* Serialize code */
+       {
+               pi->writer(pi->L, &p->sizecode, sizeof(int), pi->ud);
+               pi->writer(pi->L, p->code, sizeof(Instruction) * p->sizecode, pi->ud);
+       }
+       /* Serialize misc values */
+       {
+               pi->writer(pi->L, &p->nups, sizeof(lu_byte), pi->ud);
+               pi->writer(pi->L, &p->numparams, sizeof(lu_byte), pi->ud);
+               pi->writer(pi->L, &p->is_vararg, sizeof(lu_byte), pi->ud);
+               pi->writer(pi->L, &p->maxstacksize, sizeof(lu_byte), pi->ud);
+       }
+       /* We do not currently persist upvalue names, local variable names,
+        * variable lifetimes, line info, or source code. */
+}
+
+/* Copies a stack, but the stack is reversed in the process
+ */
+static size_t revappendstack(lua_State *from, lua_State *to)
+{
+       StkId o;
+       for(o=from->top-1; o>=from->stack; o--) {
+               setobj2s(to, to->top, o);
+               to->top++;
+       }
+       return from->top - from->stack;
+}
+
+/* Persist all stack members
+ */
+static void persistthread(PersistInfo *pi)
+{
+       size_t posremaining;
+       lua_State *L2;
+                                       /* perms reftbl ... thr */
+       L2 = lua_tothread(pi->L, -1);
+       if(pi->L == L2) {
+               lua_pushstring(pi->L, "Can't persist currently running thread");
+               lua_error(pi->L);
+               return; /* not reached */
+       }
+
+       /* Persist the stack */
+       posremaining = revappendstack(L2, pi->L);
+                                       /* perms reftbl ... thr (rev'ed contents of L2) */
+       pi->writer(pi->L, &posremaining, sizeof(size_t), pi->ud);
+       for(; posremaining > 0; posremaining--) {
+               persist(pi);
+               lua_pop(pi->L, 1);
+       }
+                                       /* perms reftbl ... thr */
+       /* Now, persist the CallInfo stack. */
+       {
+               size_t i, numframes = (L2->ci - L2->base_ci) + 1;
+               pi->writer(pi->L, &numframes, sizeof(size_t), pi->ud);
+               for(i=0; i<numframes; i++) {
+                       CallInfo *ci = L2->base_ci + i;
+                       size_t stackbase = ci->base - L2->stack;
+                       size_t stackfunc = ci->func - L2->stack;
+                       size_t stacktop = ci->top - L2->stack;
+                       size_t savedpc = (ci != L2->base_ci) ?
+                               ci->savedpc - ci_func(ci)->l.p->code :
+                               0;
+                       pi->writer(pi->L, &stackbase, sizeof(size_t), pi->ud);
+                       pi->writer(pi->L, &stackfunc, sizeof(size_t), pi->ud);
+                       pi->writer(pi->L, &stacktop, sizeof(size_t), pi->ud);
+                       pi->writer(pi->L, &ci->nresults, sizeof(int), pi->ud);
+                       pi->writer(pi->L, &savedpc, sizeof(size_t), pi->ud);
+               }
+       }
+
+       /* Serialize the state's other parameters, with the exception of upval stuff */
+       {
+               size_t stackbase = L2->base - L2->stack;
+               size_t stacktop = L2->top - L2->stack;
+               lua_assert(L2->nCcalls <= 1);
+               pi->writer(pi->L, &L2->status, sizeof(lu_byte), pi->ud);
+               pi->writer(pi->L, &stackbase, sizeof(size_t), pi->ud);
+               pi->writer(pi->L, &stacktop, sizeof(size_t), pi->ud);
+               pi->writer(pi->L, &L2->errfunc, sizeof(ptrdiff_t), pi->ud);
+       }
+
+       /* Finally, record upvalues which need to be reopened */
+       /* See the comment above persistupval() for why we do this */
+       {
+               GCObject *gco;
+               UpVal *uv;
+                                       /* perms reftbl ... thr */
+               for(gco = L2->openupval; gco != NULL; gco = uv->next) {
+                       size_t stackpos;
+                       uv = gco2uv(gco);
+
+                       /* Make sure upvalue is really open */
+                       lua_assert(uv->v != &uv->u.value);
+                       pushupval(pi->L, uv);
+                                       /* perms reftbl ... thr uv */
+                       persist(pi);
+                       lua_pop(pi->L, 1);
+                                       /* perms reftbl ... thr */
+                       stackpos = uv->v - L2->stack;
+                       pi->writer(pi->L, &stackpos, sizeof(size_t), pi->ud);
+               }
+                                       /* perms reftbl ... thr */
+               lua_pushnil(pi->L);
+                                       /* perms reftbl ... thr nil */
+               persist(pi);
+               lua_pop(pi->L, 1);
+                                       /* perms reftbl ... thr */
+       }
+                                       /* perms reftbl ... thr */
+}
+
+static void persistboolean(PersistInfo *pi)
+{
+       int b = lua_toboolean(pi->L, -1);
+       pi->writer(pi->L, &b, sizeof(int), pi->ud);
+}
+
+static void persistlightuserdata(PersistInfo *pi)
+{
+       void *p = lua_touserdata(pi->L, -1);
+       pi->writer(pi->L, &p, sizeof(void *), pi->ud);
+}
+
+static void persistnumber(PersistInfo *pi)
+{
+       lua_Number n = lua_tonumber(pi->L, -1);
+       pi->writer(pi->L, &n, sizeof(lua_Number), pi->ud);
+}
+
+static void persiststring(PersistInfo *pi)
+{
+       size_t length = lua_strlen(pi->L, -1);
+       pi->writer(pi->L, &length, sizeof(size_t), pi->ud);
+       pi->writer(pi->L, lua_tostring(pi->L, -1), length, pi->ud);
+}
+
+/* Top-level delegating persist function
+ */
+static void persist(PersistInfo *pi)
+{
+                                       /* perms reftbl ... obj */
+       /* If the object has already been written, write a reference to it */
+       lua_pushvalue(pi->L, -1);
+                                       /* perms reftbl ... obj obj */
+       lua_rawget(pi->L, 2);
+                                       /* perms reftbl ... obj ref? */
+       if(!lua_isnil(pi->L, -1)) {
+                                       /* perms reftbl ... obj ref */
+               int zero = 0;
+               int ref = (int)lua_touserdata(pi->L, -1);
+               pi->writer(pi->L, &zero, sizeof(int), pi->ud);
+               pi->writer(pi->L, &ref, sizeof(int), pi->ud);
+               lua_pop(pi->L, 1);
+                                       /* perms reftbl ... obj ref */
+#ifdef PLUTO_DEBUG
+               printindent(pi->level);
+               printf("0 %d\n", ref);
+#endif
+               return;
+       }
+                                       /* perms reftbl ... obj nil */
+       lua_pop(pi->L, 1);
+                                       /* perms reftbl ... obj */
+       /* If the object is nil, write the pseudoreference 0 */
+       if(lua_isnil(pi->L, -1)) {
+               int zero = 0;
+               /* firsttime */
+               pi->writer(pi->L, &zero, sizeof(int), pi->ud);
+               /* ref */
+               pi->writer(pi->L, &zero, sizeof(int), pi->ud);
+#ifdef PLUTO_DEBUG
+               printindent(pi->level);
+               printf("0 0\n");
+#endif
+               return;
+       }
+       {
+               /* indicate that it's the first time */
+               int one = 1;
+               pi->writer(pi->L, &one, sizeof(int), pi->ud);
+       }
+       lua_pushvalue(pi->L, -1);
+                                       /* perms reftbl ... obj obj */
+       lua_pushlightuserdata(pi->L, (void*)(++(pi->counter)));
+                                       /* perms reftbl ... obj obj ref */
+       lua_rawset(pi->L, 2);
+                                       /* perms reftbl ... obj */
+
+       pi->writer(pi->L, &pi->counter, sizeof(int), pi->ud);
+
+
+       /* At this point, we'll give the permanents table a chance to play. */
+       {
+               lua_pushvalue(pi->L, -1);
+                                       /* perms reftbl ... obj obj */
+               lua_gettable(pi->L, 1);
+                                       /* perms reftbl ... obj permkey? */
+               if(!lua_isnil(pi->L, -1)) {
+                                       /* perms reftbl ... obj permkey */
+                       int type = PLUTO_TPERMANENT;
+#ifdef PLUTO_DEBUG
+                       printindent(pi->level);
+                       printf("1 %d PERM\n", pi->counter);
+                       pi->level++;
+#endif
+                       pi->writer(pi->L, &type, sizeof(int), pi->ud);
+                       persist(pi);
+                       lua_pop(pi->L, 1);
+                                       /* perms reftbl ... obj */
+#ifdef PLUTO_DEBUG
+                       pi->level--;
+#endif
+                       return;
+               } else {
+                                       /* perms reftbl ... obj nil */
+                       lua_pop(pi->L, 1);
+                                       /* perms reftbl ... obj */
+               }
+                                       /* perms reftbl ... obj */
+       }
+       {
+               int type = lua_type(pi->L, -1);
+               pi->writer(pi->L, &type, sizeof(int), pi->ud);
+
+#ifdef PLUTO_DEBUG
+               printindent(pi->level);
+               printf("1 %d %d\n", pi->counter, type);
+               pi->level++;
+#endif
+       }
+
+       switch(lua_type(pi->L, -1)) {
+               case LUA_TBOOLEAN:
+                       persistboolean(pi);
+                       break;
+               case LUA_TLIGHTUSERDATA:
+                       persistlightuserdata(pi);
+                       break;
+               case LUA_TNUMBER:
+                       persistnumber(pi);
+                       break;
+               case LUA_TSTRING:
+                       persiststring(pi);
+                       break;
+               case LUA_TTABLE:
+                       persisttable(pi);
+                       break;
+               case LUA_TFUNCTION:
+                       persistfunction(pi);
+                       break;
+               case LUA_TTHREAD:
+                       persistthread(pi);
+                       break;
+               case LUA_TPROTO:
+                       persistproto(pi);
+                       break;
+               case LUA_TUPVAL:
+                       persistupval(pi);
+                       break;
+               case LUA_TUSERDATA:
+                       persistuserdata(pi);
+                       break;
+               default:
+                       lua_assert(0);
+       }
+#ifdef PLUTO_DEBUG
+       pi->level--;
+#endif
+}
+
+void pluto_persist(lua_State *L, lua_Chunkwriter writer, void *ud)
+{
+       PersistInfo pi;
+
+       pi.counter = 0;
+       pi.L = L;
+       pi.writer = writer;
+       pi.ud = ud;
+#ifdef PLUTO_DEBUG
+       pi.level = 0;
+#endif
+
+                                       /* perms? rootobj? ...? */
+       lua_assert(lua_gettop(L) == 2);
+                                       /* perms rootobj */
+       lua_assert(!lua_isnil(L, 2));
+                                       /* perms rootobj */
+       lua_newtable(L);
+                                       /* perms rootobj reftbl */
+
+       /* Now we're going to make the table weakly keyed. This prevents the
+        * GC from visiting it and trying to mark things it doesn't want to
+        * mark in tables, e.g. upvalues. All objects in the table are
+        * a priori reachable, so it doesn't matter that we do this. */
+       lua_newtable(L);
+                                       /* perms rootobj reftbl mt */
+       lua_pushstring(L, "__mode");
+                                       /* perms rootobj reftbl mt "__mode" */
+       lua_pushstring(L, "k");
+                                       /* perms rootobj reftbl mt "__mode" "k" */
+       lua_settable(L, 4);
+                                       /* perms rootobj reftbl mt */
+       lua_setmetatable(L, 3);
+                                       /* perms rootobj reftbl */
+       lua_insert(L, 2);
+                                       /* perms reftbl rootobj */
+       persist(&pi);
+                                       /* perms reftbl rootobj */
+       lua_remove(L, 2);
+                                       /* perms rootobj */
+}
+
+typedef struct WriterInfo_t {
+       char* buf;
+       size_t buflen;
+} WriterInfo;
+
+static int bufwriter (lua_State *L, const void* p, size_t sz, void* ud) {
+       const char* cp = (const char*)p;
+       WriterInfo *wi = (WriterInfo *)ud;
+
+       LIF(M,reallocvector)(L, wi->buf, wi->buflen, wi->buflen+sz, char);
+       while(sz)
+       {
+               /* how dearly I love ugly C pointer twiddling */
+               wi->buf[wi->buflen++] = *cp++;
+               sz--;
+       }
+       return 0;
+}
+
+int persist_l(lua_State *L)
+{
+                                       /* perms? rootobj? ...? */
+       WriterInfo wi;
+
+       wi.buf = NULL;
+       wi.buflen = 0;
+
+       lua_settop(L, 2);
+                                       /* perms? rootobj? */
+       luaL_checktype(L, 1, LUA_TTABLE);
+                                       /* perms rootobj? */
+       luaL_checktype(L, 1, LUA_TTABLE);
+                                       /* perms rootobj */
+
+       pluto_persist(L, bufwriter, &wi);
+
+       lua_settop(L, 0);
+                                       /* (empty) */
+       lua_pushlstring(L, wi.buf, wi.buflen);
+                                       /* str */
+       pdep_freearray(L, wi.buf, wi.buflen, char);
+       return 1;
+}
+
+typedef struct UnpersistInfo_t {
+       lua_State *L;
+       ZIO zio;
+#ifdef PLUTO_DEBUG
+       int level;
+#endif
+} UnpersistInfo;
+
+static void unpersist(UnpersistInfo *upi);
+
+/* The object is left on the stack. This is primarily used by unpersist, but
+ * may be used by GCed objects that may incur cycles in order to preregister
+ * the object. */
+static void registerobject(int ref, UnpersistInfo *upi)
+{
+                                       /* perms reftbl ... obj */
+       lua_pushlightuserdata(upi->L, (void*)ref);
+                                       /* perms reftbl ... obj ref */
+       lua_pushvalue(upi->L, -2);
+                                       /* perms reftbl ... obj ref obj */
+       lua_settable(upi->L, 2);
+                                       /* perms reftbl ... obj */
+}
+
+static void unpersistboolean(UnpersistInfo *upi)
+{
+                                       /* perms reftbl ... */
+       int b;
+       verify(LIF(Z,read)(&upi->zio, &b, sizeof(int)) == 0);
+       lua_pushboolean(upi->L, b);
+                                       /* perms reftbl ... bool */
+}
+
+static void unpersistlightuserdata(UnpersistInfo *upi)
+{
+                                       /* perms reftbl ... */
+       void *p;
+       verify(LIF(Z,read)(&upi->zio, &p, sizeof(void *)) == 0);
+       lua_pushlightuserdata(upi->L, p);
+                                       /* perms reftbl ... ludata */
+}
+
+static void unpersistnumber(UnpersistInfo *upi)
+{
+                                       /* perms reftbl ... */
+       lua_Number n;
+       verify(LIF(Z,read)(&upi->zio, &n, sizeof(lua_Number)) == 0);
+       lua_pushnumber(upi->L, n);
+                                       /* perms reftbl ... num */
+}
+
+static void unpersiststring(UnpersistInfo *upi)
+{
+                                       /* perms reftbl sptbl ref */
+       size_t length;
+       char* string;
+       verify(LIF(Z,read)(&upi->zio, &length, sizeof(size_t)) == 0);
+       string = pdep_newvector(upi->L, length, char);
+       verify(LIF(Z,read)(&upi->zio, string, length) == 0);
+       lua_pushlstring(upi->L, string, length);
+                                       /* perms reftbl sptbl ref str */
+       pdep_freearray(upi->L, string, length, char);
+}
+
+static void unpersistspecialtable(int ref, UnpersistInfo *upi)
+{
+                                       /* perms reftbl ... */
+       unpersist(upi);
+                                       /* perms reftbl ... spfunc? */
+       lua_assert(lua_isfunction(upi->L, -1));
+                                       /* perms reftbl ... spfunc */
+       lua_call(upi->L, 0, 1);
+                                       /* perms reftbl ... tbl? */
+       lua_assert(lua_istable(upi->L, -1));
+                                       /* perms reftbl ... tbl */
+}
+
+static void unpersistliteraltable(int ref, UnpersistInfo *upi)
+{
+                                       /* perms reftbl ... */
+       /* Preregister table for handling of cycles */
+       lua_newtable(upi->L);
+                                       /* perms reftbl ... tbl */
+       registerobject(ref, upi);
+                                       /* perms reftbl ... tbl */
+       /* Unpersist metatable */
+       {
+               unpersist(upi);
+                                       /* perms reftbl ... tbl mt/nil? */
+               if(lua_istable(upi->L, -1)) {
+                                       /* perms reftbl ... tbl mt */
+                       lua_setmetatable(upi->L, -2);
+                                       /* perms reftbl ... tbl */
+               } else {
+                                       /* perms reftbl ... tbl nil? */
+                       lua_assert(lua_isnil(upi->L, -1));
+                                       /* perms reftbl ... tbl nil */
+                       lua_pop(upi->L, 1);
+                                       /* perms reftbl ... tbl */
+               }
+                                       /* perms reftbl ... tbl */
+       }
+
+       while(1)
+       {
+                                       /* perms reftbl ... tbl */
+               unpersist(upi);
+                                       /* perms reftbl ... tbl key/nil */
+               if(lua_isnil(upi->L, -1)) {
+                                       /* perms reftbl ... tbl nil */
+                       lua_pop(upi->L, 1);
+                                       /* perms reftbl ... tbl */
+                       break;
+               }
+                                       /* perms reftbl ... tbl key */
+               unpersist(upi);
+                                       /* perms reftbl ... tbl key value? */
+               lua_assert(!lua_isnil(upi->L, -1));
+                                       /* perms reftbl ... tbl key value */
+               lua_rawset(upi->L, -3);
+                                       /* perms reftbl ... tbl */
+       }
+}
+
+static void unpersisttable(int ref, UnpersistInfo *upi)
+{
+                                       /* perms reftbl ... */
+       {
+               int isspecial;
+               verify(LIF(Z,read)(&upi->zio, &isspecial, sizeof(int)) == 0);
+               if(isspecial) {
+                       unpersistspecialtable(ref, upi);
+                                       /* perms reftbl ... tbl */
+               } else {
+                       unpersistliteraltable(ref, upi);
+                                       /* perms reftbl ... tbl */
+               }
+                                       /* perms reftbl ... tbl */
+       }
+}
+
+static UpVal *makeupval(lua_State *L, int stackpos)
+{
+       UpVal *uv = pdep_new(L, UpVal);
+       pdep_link(L, (GCObject*)uv, LUA_TUPVAL);
+       uv->tt = LUA_TUPVAL;
+       uv->v = &uv->u.value;
+       uv->u.l.prev = NULL;
+       uv->u.l.next = NULL;
+       setobj(L, uv->v, getobject(L, stackpos));
+       return uv;
+}
+
+static Proto *makefakeproto(lua_State *L, lu_byte nups)
+{
+       Proto *p = pdep_newproto(L);
+       p->sizelineinfo = 1;
+       p->lineinfo = pdep_newvector(L, 1, int);
+       p->lineinfo[0] = 1;
+       p->sizecode = 1;
+       p->code = pdep_newvector(L, 1, Instruction);
+       p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0);
+       p->source = pdep_newlstr(L, "", 0);
+       p->maxstacksize = 2;
+       p->nups = nups;
+       p->sizek = 0;
+       p->sizep = 0;
+
+       return p;
+}
+
+/* The GC is not fond of finding upvalues in tables. We get around this
+ * during persistence using a weakly keyed table, so that the GC doesn't
+ * bother to mark them. This won't work in unpersisting, however, since
+ * if we make the values weak they'll be collected (since nothing else
+ * references them). Our solution, during unpersisting, is to represent
+ * upvalues as dummy functions, each with one upvalue. */
+static void boxupval_start(lua_State *L)
+{
+       LClosure *lcl;
+       lcl = (LClosure*)pdep_newLclosure(L, 1, hvalue(&L->l_gt));
+       pushclosure(L, (Closure*)lcl);
+                                       /* ... func */
+       lcl->p = makefakeproto(L, 1);
+
+       /* Temporarily initialize the upvalue to nil */
+
+       lua_pushnil(L);
+       lcl->upvals[0] = makeupval(L, -1);
+       lua_pop(L, 1);
+}
+
+static void boxupval_finish(lua_State *L)
+{
+                                       /* ... func upval */
+       UpVal *uv;
+       LClosure *lcl = (LClosure *) clvalue(getobject(L, -2));
+
+       uv = toupval(L, -1);
+       lua_pop(L, 1);
+                                       /* ... func */
+       lcl->p->nups = 1;
+       lcl->upvals[0] = uv;
+}
+
+
+static void unboxupval(lua_State *L)
+{
+                                       /* ... func */
+       LClosure *lcl;
+       UpVal *uv;
+
+       lcl = (LClosure*)clvalue(getobject(L, -1));
+       uv = lcl->upvals[0];
+       lua_pop(L, 1);
+                                       /* ... */
+       pushupval(L, uv);
+                                       /* ... upval */
+}
+
+static void unpersistfunction(int ref, UnpersistInfo *upi)
+{
+                                       /* perms reftbl ... */
+       LClosure *lcl;
+       int i;
+       lu_byte nupvalues;
+
+       verify(LIF(Z,read)(&upi->zio, &nupvalues, sizeof(lu_byte)) == 0);
+
+       lcl = (LClosure*)pdep_newLclosure(upi->L, nupvalues, hvalue(&upi->L->l_gt));
+       pushclosure(upi->L, (Closure*)lcl);
+
+                                       /* perms reftbl ... func */
+       /* Put *some* proto in the closure, before the GC can find it */
+       lcl->p = makefakeproto(upi->L, nupvalues);
+
+       /* Also, we need to temporarily fill the upvalues */
+       lua_pushnil(upi->L);
+                                       /* perms reftbl ... func nil */
+       for(i=0; i<nupvalues; i++) {
+               lcl->upvals[i] = makeupval(upi->L, -1);
+       }
+       lua_pop(upi->L, 1);
+                                       /* perms reftbl ... func */
+
+       /* I can't see offhand how a function would ever get to be self-
+        * referential, but just in case let's register it early */
+       registerobject(ref, upi);
+
+       /* Now that it's safe, we can get the real proto */
+       unpersist(upi);
+                                       /* perms reftbl ... func proto? */
+       lua_assert(lua_type(upi->L, -1) == LUA_TPROTO);
+                                       /* perms reftbl ... func proto */
+       lcl->p = toproto(upi->L, -1);
+       lua_pop(upi->L, 1);
+                                       /* perms reftbl ... func */
+
+       for(i=0; i<nupvalues; i++) {
+                                       /* perms reftbl ... func */
+               unpersist(upi);
+                                       /* perms reftbl ... func func2 */
+               unboxupval(upi->L);
+                                       /* perms reftbl ... func upval */
+               lcl->upvals[i] = toupval(upi->L, -1);
+               lua_pop(upi->L, 1);
+                                       /* perms reftbl ... func */
+       }
+                                       /* perms reftbl ... func */
+
+       /* Finally, the fenv */
+       unpersist(upi);
+                                       /* perms reftbl ... func fenv/nil? */
+       lua_assert(lua_type(upi->L, -1) == LUA_TNIL ||
+               lua_type(upi->L, -1) == LUA_TTABLE);
+                                       /* perms reftbl ... func fenv/nil */
+       if(!lua_isnil(upi->L, -1)) {
+                                       /* perms reftbl ... func fenv */
+               lua_setfenv(upi->L, -2);
+                                       /* perms reftbl ... func */
+       } else {
+                                       /* perms reftbl ... func nil */
+               lua_pop(upi->L, 1);
+                                       /* perms reftbl ... func */
+       }
+                                       /* perms reftbl ... func */
+}
+
+static void unpersistupval(int ref, UnpersistInfo *upi)
+{
+                                       /* perms reftbl ... */
+       UpVal *uv;
+
+       boxupval_start(upi->L);
+                                       /* perms reftbl ... func */
+       registerobject(ref, upi);
+
+       unpersist(upi);
+                                       /* perms reftbl ... func obj */
+       uv = makeupval(upi->L, -1);
+       lua_pop(upi->L, 1);
+                                       /* perms reftbl ... func */
+       pushupval(upi->L, uv);
+                                       /* perms reftbl ... func upval */
+       boxupval_finish(upi->L);
+                                       /* perms reftbl ... func */
+}
+
+static void unpersistproto(int ref, UnpersistInfo *upi)
+{
+                                       /* perms reftbl ... */
+       Proto *p;
+       int i;
+       int sizep, sizek;
+
+       /* We have to be careful. The GC expects a lot out of protos. In
+        * particular, we need to give the function a valid string for its
+        * source, and valid code, even before we actually read in the real
+        * code. */
+       TString *source = pdep_newlstr(upi->L, "", 0);
+       p = pdep_newproto(upi->L);
+       p->source = source;
+       p->sizecode=1;
+       p->code = pdep_newvector(upi->L, 1, Instruction);
+       p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0);
+       p->maxstacksize = 2;
+       p->sizek = 0;
+       p->sizep = 0;
+
+
+       pushproto(upi->L, p);
+                                       /* perms reftbl ... proto */
+       /* We don't need to register early, since protos can never ever be
+        * involved in cyclic references */
+
+       /* Read in constant references */
+       {
+               verify(LIF(Z,read)(&upi->zio, &sizek, sizeof(int)) == 0);
+               LIF(M,reallocvector)(upi->L, p->k, 0, sizek, TValue);
+               for(i=0; i<sizek; i++) {
+                                       /* perms reftbl ... proto */
+                       unpersist(upi);
+                                       /* perms reftbl ... proto k */
+                       setobj2s(upi->L, &p->k[i], getobject(upi->L, -1));
+                       p->sizek++;
+                       lua_pop(upi->L, 1);
+                                       /* perms reftbl ... proto */
+               }
+                                       /* perms reftbl ... proto */
+       }
+       /* Read in sub-proto references */
+       {
+               verify(LIF(Z,read)(&upi->zio, &sizep, sizeof(int)) == 0);
+               LIF(M,reallocvector)(upi->L, p->p, 0, sizep, Proto*);
+               for(i=0; i<sizep; i++) {
+                                       /* perms reftbl ... proto */
+                       unpersist(upi);
+                                       /* perms reftbl ... proto subproto */
+                       p->p[i] = toproto(upi->L, -1);
+                       p->sizep++;
+                       lua_pop(upi->L, 1);
+                                       /* perms reftbl ... proto */
+               }
+                                       /* perms reftbl ... proto */
+       }
+
+       /* Read in code */
+       {
+               verify(LIF(Z,read)(&upi->zio, &p->sizecode, sizeof(int)) == 0);
+               LIF(M,reallocvector)(upi->L, p->code, 1, p->sizecode, Instruction);
+               verify(LIF(Z,read)(&upi->zio, p->code,
+                       sizeof(Instruction) * p->sizecode) == 0);
+       }
+
+       /* Read in misc values */
+       {
+               verify(LIF(Z,read)(&upi->zio, &p->nups, sizeof(lu_byte)) == 0);
+               verify(LIF(Z,read)(&upi->zio, &p->numparams, sizeof(lu_byte)) == 0);
+               verify(LIF(Z,read)(&upi->zio, &p->is_vararg, sizeof(lu_byte)) == 0);
+               verify(LIF(Z,read)(&upi->zio, &p->maxstacksize, sizeof(lu_byte)) == 0);
+       }
+}
+
+
+/* Does basically the opposite of luaC_link().
+ * Right now this function is rather inefficient; it requires traversing the
+ * entire root GC set in order to find one object. If the GC list were doubly
+ * linked this would be much easier, but there's no reason for Lua to have
+ * that. */
+static void gcunlink(lua_State *L, GCObject *gco)
+{
+       GCObject *prevslot;
+       if(G(L)->rootgc == gco) {
+               G(L)->rootgc = G(L)->rootgc->gch.next;
+               return;
+       }
+
+       prevslot = G(L)->rootgc;
+       while(prevslot->gch.next != gco) {
+               lua_assert(prevslot->gch.next != NULL);
+               prevslot = prevslot->gch.next;
+       }
+
+       prevslot->gch.next = prevslot->gch.next->gch.next;
+}
+
+/* FIXME __ALL__ field ordering */
+static void unpersistthread(int ref, UnpersistInfo *upi)
+{
+                                       /* perms reftbl ... */
+       lua_State *L2;
+       size_t stacklimit = 0;
+       L2 = lua_newthread(upi->L);
+                                       /* L1: perms reftbl ... thr */
+                                       /* L2: (empty) */
+       registerobject(ref, upi);
+
+       /* First, deserialize the object stack. */
+       {
+               size_t i, stacksize;
+               verify(LIF(Z,read)(&upi->zio, &stacksize, sizeof(size_t)) == 0);
+               LIF(D,growstack)(L2, (int)stacksize);
+               /* Make sure that the first stack element (a nil, representing
+                * the imaginary top-level C function) is written to the very,
+                * very bottom of the stack */
+               L2->top--;
+               for(i=0; i<stacksize; i++) {
+                       unpersist(upi);
+                                       /* L1: perms reftbl ... thr obj* */
+               }
+               lua_xmove(upi->L, L2, stacksize);
+                                       /* L1: perms reftbl ... thr */
+                                       /* L2: obj* */
+       }
+                                       /* (hereafter, stacks refer to L1) */
+
+       /* Now, deserialize the CallInfo stack. */
+       {
+               size_t i, numframes;
+               verify(LIF(Z,read)(&upi->zio, &numframes, sizeof(size_t)) == 0);
+               LIF(D,reallocCI)(L2,numframes*2);
+               for(i=0; i<numframes; i++) {
+                       CallInfo *ci = L2->base_ci + i;
+                       size_t stackbase, stackfunc, stacktop, savedpc;
+                       verify(LIF(Z,read)(&upi->zio, &stackbase, sizeof(size_t)) == 0);
+                       verify(LIF(Z,read)(&upi->zio, &stackfunc, sizeof(size_t)) == 0);
+                       verify(LIF(Z,read)(&upi->zio, &stacktop, sizeof(size_t)) == 0);
+                       verify(LIF(Z,read)(&upi->zio, &ci->nresults, sizeof(int)) == 0);
+                       verify(LIF(Z,read)(&upi->zio, &savedpc, sizeof(size_t)) == 0);
+                       
+                       if(stacklimit < stacktop)
+                               stacklimit = stacktop;
+                       
+                       ci->base = L2->stack+stackbase;
+                       ci->func = L2->stack+stackfunc;
+                       ci->top = L2->stack+stacktop;
+                       ci->savedpc = (ci != L2->base_ci) ?
+                               ci_func(ci)->l.p->code+savedpc :
+                               0;
+                       ci->tailcalls = 0;
+                       /* Update the pointer each time, to keep the GC
+                        * happy*/
+                       L2->ci = ci;
+               }
+       }
+                                       /* perms reftbl ... thr */
+       /* Deserialize the state's other parameters, with the exception of upval stuff */
+       {
+               size_t stackbase, stacktop;
+               L2->savedpc = L2->ci->savedpc;
+               verify(LIF(Z,read)(&upi->zio, &L2->status, sizeof(lu_byte)) == 0);
+               verify(LIF(Z,read)(&upi->zio, &stackbase, sizeof(size_t)) == 0);
+               verify(LIF(Z,read)(&upi->zio, &stacktop, sizeof(size_t)) == 0);
+               verify(LIF(Z,read)(&upi->zio, &L2->errfunc, sizeof(ptrdiff_t)) == 0);
+               L2->base = L2->stack + stackbase;
+               L2->top = L2->stack + stacktop;
+       }
+       /* Finally, "reopen" upvalues (see persistupval() for why) */
+       {
+               UpVal* uv;
+               GCObject **nextslot = &L2->openupval;
+               global_State *g = G(L2);
+               while(1) {
+                       size_t stackpos;
+                       unpersist(upi);
+                                       /* perms reftbl ... thr uv/nil */
+                       if(lua_isnil(upi->L, -1)) {
+                                       /* perms reftbl ... thr nil */
+                               lua_pop(upi->L, 1);
+                                       /* perms reftbl ... thr */
+                               break;
+                       }
+                                       /* perms reftbl ... thr boxeduv */
+                       unboxupval(upi->L);
+                                       /* perms reftbl ... thr uv */
+                       uv = toupval(upi->L, -1);
+                       lua_pop(upi->L, 1);
+                                       /* perms reftbl ... thr */
+
+                       verify(LIF(Z,read)(&upi->zio, &stackpos, sizeof(size_t)) == 0);
+                       uv->v = L2->stack + stackpos;
+                       gcunlink(upi->L, (GCObject*)uv);
+                       uv->marked = luaC_white(g);
+                       *nextslot = (GCObject*)uv;
+                       nextslot = &uv->next;
+                       uv->u.l.prev = &G(L2)->uvhead;
+                       uv->u.l.next = G(L2)->uvhead.u.l.next;
+                       uv->u.l.next->u.l.prev = uv;
+                       G(L2)->uvhead.u.l.next = uv;
+                       lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
+               }
+               *nextslot = NULL;
+       }
+       
+       /* The stack must be valid at least to the highest value among the CallInfos */
+       /* 'top' and the values up to there must be filled with 'nil' */
+       {
+               StkId o;
+               LIF(D,checkstack)(L2, (int)stacklimit);
+               for (o = L2->top; o <= L2->top + stacklimit; o++)
+                       setnilvalue(o);
+       }
+}
+
+static void unpersistuserdata(int ref, UnpersistInfo *upi)
+{
+                                       /* perms reftbl ... */
+       int isspecial;
+       verify(LIF(Z,read)(&upi->zio, &isspecial, sizeof(int)) == 0);
+       if(isspecial) {
+               unpersist(upi);
+                                       /* perms reftbl ... spfunc? */
+               lua_assert(lua_isfunction(upi->L, -1));
+                                       /* perms reftbl ... spfunc */
+#ifdef PLUTO_PASS_USERDATA_TO_PERSIST
+               lua_pushlightuserdata(upi->L, &upi->zio);
+               lua_call(upi->L, 1, 1);
+#else
+               lua_call(upi->L, 0, 1);
+#endif
+                                       /* perms reftbl ... udata? */
+/* This assertion might not be necessary; it's conceivable, for
+ * example, that the SP function might decide to return a table
+ * with equivalent functionality. For the time being, we'll
+ * ignore this possibility in favor of stricter and more testable
+ * requirements. */
+               lua_assert(lua_isuserdata(upi->L, -1));
+                                       /* perms reftbl ... udata */
+       } else {
+               size_t length;
+               verify(LIF(Z,read)(&upi->zio, &length, sizeof(size_t)) == 0);
+
+               lua_newuserdata(upi->L, length);
+                                       /* perms reftbl ... udata */
+               registerobject(ref, upi);
+               verify(LIF(Z,read)(&upi->zio, lua_touserdata(upi->L, -1), length) == 0);
+
+               unpersist(upi);
+                                       /* perms reftbl ... udata mt/nil? */
+               lua_assert(lua_istable(upi->L, -1) || lua_isnil(upi->L, -1));
+                                       /* perms reftbl ... udata mt/nil */
+               lua_setmetatable(upi->L, -2);
+                                       /* perms reftbl ... udata */
+       }
+                                       /* perms reftbl ... udata */
+}
+
+static void unpersistpermanent(int ref, UnpersistInfo *upi)
+{
+                                       /* perms reftbl ... */
+       unpersist(upi);
+                                       /* perms reftbl permkey */
+       lua_gettable(upi->L, 1);
+                                       /* perms reftbl perm? */
+       /* We assume currently that the substituted permanent value
+        * shouldn't be nil. This may be a bad assumption. Real-life
+        * experience is needed to evaluate this. */
+       lua_assert(!lua_isnil(upi->L, -1));
+                                       /* perms reftbl perm */
+}
+
+/* For debugging only; not called when lua_assert is empty */
+static int inreftable(lua_State *L, int ref)
+{
+       int res;
+                                       /* perms reftbl ... */
+       lua_pushlightuserdata(L, (void*)ref);
+                                       /* perms reftbl ... ref */
+       lua_gettable(L, 2);
+                                       /* perms reftbl ... obj? */
+       res = !lua_isnil(L, -1);
+       lua_pop(L, 1);
+                                       /* perms reftbl ... */
+       return res;
+}
+
+static void unpersist(UnpersistInfo *upi)
+{
+                                       /* perms reftbl ... */
+       int firstTime;
+       int stacksize = lua_gettop(upi->L); stacksize = stacksize; /* DEBUG */
+       LIF(Z,read)(&upi->zio, &firstTime, sizeof(int));
+       if(firstTime) {
+               int ref;
+               int type;
+               LIF(Z,read)(&upi->zio, &ref, sizeof(int));
+               lua_assert(!inreftable(upi->L, ref));
+               LIF(Z,read)(&upi->zio, &type, sizeof(int));
+#ifdef PLUTO_DEBUG
+               printindent(upi->level);
+               printf("1 %d %d\n", ref, type);
+               upi->level++;
+#endif
+               switch(type) {
+               case LUA_TBOOLEAN:
+                       unpersistboolean(upi);
+                       break;
+               case LUA_TLIGHTUSERDATA:
+                       unpersistlightuserdata(upi);
+                       break;
+               case LUA_TNUMBER:
+                       unpersistnumber(upi);
+                       break;
+               case LUA_TSTRING:
+                       unpersiststring(upi);
+                       break;
+               case LUA_TTABLE:
+                       unpersisttable(ref, upi);
+                       break;
+               case LUA_TFUNCTION:
+                       unpersistfunction(ref, upi);
+                       break;
+               case LUA_TTHREAD:
+                       unpersistthread(ref, upi);
+                       break;
+               case LUA_TPROTO:
+                       unpersistproto(ref, upi);
+                       break;
+               case LUA_TUPVAL:
+                       unpersistupval(ref, upi);
+                       break;
+               case LUA_TUSERDATA:
+                       unpersistuserdata(ref, upi);
+                       break;
+               case PLUTO_TPERMANENT:
+                       unpersistpermanent(ref, upi);
+                       break;
+               default:
+                       lua_assert(0);
+               }
+                                       /* perms reftbl ... obj */
+               lua_assert(lua_type(upi->L, -1) == type ||
+                       type == PLUTO_TPERMANENT ||
+                       /* Remember, upvalues get a special dispensation, as
+                        * described in boxupval */
+                       (lua_type(upi->L, -1) == LUA_TFUNCTION &&
+                               type == LUA_TUPVAL));
+               registerobject(ref, upi);
+                                       /* perms reftbl ... obj */
+#ifdef PLUTO_DEBUG
+               upi->level--;
+#endif
+       } else {
+               int ref;
+               LIF(Z,read)(&upi->zio, &ref, sizeof(int));
+#ifdef PLUTO_DEBUG
+               printindent(upi->level);
+               printf("0 %d\n", ref);
+#endif
+               if(ref == 0) {
+                       lua_pushnil(upi->L);
+                                       /* perms reftbl ... nil */
+               } else {
+                       lua_pushlightuserdata(upi->L, (void*)ref);
+                                       /* perms reftbl ... ref */
+                       lua_gettable(upi->L, 2);
+                                       /* perms reftbl ... obj? */
+                       lua_assert(!lua_isnil(upi->L, -1));
+               }
+                                       /* perms reftbl ... obj/nil */
+       }
+                                       /* perms reftbl ... obj/nil */
+       lua_assert(lua_gettop(upi->L) == stacksize + 1);
+}
+
+void pluto_unpersist(lua_State *L, lua_Chunkreader reader, void *ud)
+{
+       /* We use the graciously provided ZIO (what the heck does the Z stand
+        * for?) library so that we don't have to deal with the reader directly.
+        * Letting the reader function decide how much data to return can be
+        * very unpleasant.
+        */
+       UnpersistInfo upi;
+       upi.L = L;
+#ifdef PLUTO_DEBUG
+       upi.level = 0;
+#endif
+
+       LIF(Z,init)(L, &upi.zio, reader, ud);
+
+                                       /* perms */
+       lua_newtable(L);
+                                       /* perms reftbl */
+       lua_gc(L, LUA_GCSTOP, 0);
+       unpersist(&upi);
+       lua_gc(L, LUA_GCRESTART, 0);
+                                       /* perms reftbl rootobj */
+       lua_replace(L, 2);
+                                       /* perms rootobj  */
+}
+
+typedef struct LoadInfo_t {
+  char *buf;
+  size_t size;
+} LoadInfo;
+
+
+static const char *bufreader(lua_State *L, void *ud, size_t *sz) {
+       LoadInfo *li = (LoadInfo *)ud;
+       if(li->size == 0) {
+               return NULL;
+       }
+       *sz = li->size;
+       li->size = 0;
+       return li->buf;
+}
+
+int unpersist_l(lua_State *L)
+{
+       LoadInfo li;
+       char const *origbuf;
+       char *tempbuf;
+       size_t bufsize;
+                                       /* perms? str? ...? */
+       lua_settop(L, 2);
+                                       /* perms? str? */
+       origbuf = luaL_checklstring(L, 2, &bufsize);
+       tempbuf = LIF(M,newvector)(L, bufsize, char);
+       memcpy(tempbuf, origbuf, bufsize);
+
+       li.buf = tempbuf;
+       li.size = bufsize;
+
+                                       /* perms? str */
+       lua_pop(L, 1);
+                                       /* perms? */
+       luaL_checktype(L, 1, LUA_TTABLE);
+                                       /* perms */
+       pluto_unpersist(L, bufreader, &li);
+                                       /* perms rootobj */
+       LIF(M,freearray)(L, tempbuf, bufsize, char);
+       return 1;
+}
+
+static luaL_reg pluto_reg[] = {
+       { "persist", persist_l },
+       { "unpersist", unpersist_l },
+       { NULL, NULL }
+};
+
+int luaopen_pluto(lua_State *L) {
+       luaL_openlib(L, "pluto", pluto_reg, 0);
+       return 1;
+}
diff --git a/src/binlibs/pluto/pluto.h b/src/binlibs/pluto/pluto.h
new file mode 100644 (file)
index 0000000..7da4e16
--- /dev/null
@@ -0,0 +1,25 @@
+/* $Id$ */
+
+/* Pluto - Heavy-duty persistence for Lua
+ * Copyright (C) 2004 by Ben Sunshine-Hill, and released into the public 
+ * domain. People making use of this software as part of an application
+ * are politely requested to email the author at sneftel@gmail.com 
+ * with a brief description of the application, primarily to satisfy his
+ * curiosity.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* lua.h must be included before this file */
+
+void pluto_persist(lua_State *L, lua_Chunkwriter writer, void *ud);
+
+void pluto_unpersist(lua_State *L, lua_Chunkreader reader, void *ud);
+
+int luaopen_pluto(lua_State *L);
index 561e7c3ace986b09a965418a579567037358b3ec..02f1b42f523aed5d7ef293bf2fc637ab9429e2a6 100644 (file)
@@ -51,7 +51,7 @@ mlp.luac: $(MLP_LUA)
 
 # Compiler/interpreter
 metalua: metalua.luac $(LIBRARIES)
-       $(LUA_RUN) metalua.luac --verbose --sharpbang '#!/usr/bin/env lua' --output metalua --file metalua.mlua
+       $(LUA_RUN) metalua.luac --verbose --sharpbang '#!$(TARGET_BIN_PATH)/lua' --output metalua --file metalua.mlua
 
 install: metalua $(LIBRARIES)
        mkdir -p $(TARGET_BIN_PATH)
index 39393fb607985587245511613c907c669c2e4330..f2ef5da4e8094686eb9f0a51199b225708949d52 100644 (file)
 
 module("bytecode", package.seeall)
 
+local cfg = { }
+cfg.little_endian, cfg.int_size, 
+cfg.size_t_size,   cfg.instr_size, 
+cfg.number_size,   cfg.integral = 
+   string.dump(function()end):byte(7, 12)
+
+--for k, v in pairs(cfg) do
+--   printf("%s:\t%i", k, v)
+--end
+
+assert(cfg.number_size==8, "Number format not supported by dumper")
+assert(cfg.little_endian==1, "Big endian architectures not supported by dumper")
+
 --requires luaP
 luaU = {}
 
@@ -166,17 +179,17 @@ end
 -- converts a number to a little-endian 32-bit integer string
 -- * input value assumed to not overflow, can be signed/unsigned
 -----------------------------------------------------------------------
-function luaU:from_int(x)
+function luaU:from_int(x, size)
   local v = ""
   x = math.floor(x)
   if x >= 0 then
-    for i = 1, 4 do
+    for i = 1, size do
       v = v..string.char(math.mod(x, 256)); x = math.floor(x / 256)
     end
   else -- x < 0
     x = -x
     local carry = 1
-    for i = 1, 4 do
+    for i = 1, size do
       local c = 255 - math.mod(x, 256) + carry
       if c == 256 then c = 0; carry = 1 else carry = 0 end
       v = v..string.char(c); x = math.floor(x / 256)
@@ -221,14 +234,14 @@ end
 -- dumps a 32-bit signed integer (for int)
 ------------------------------------------------------------------------
 function luaU:DumpInt(x, D)
-  self:DumpBlock(self:from_int(x), D)
+  self:DumpBlock(self:from_int(x, cfg.int_size), D)
 end
 
 ------------------------------------------------------------------------
 -- dumps a 32-bit unsigned integer (for size_t)
 ------------------------------------------------------------------------
 function luaU:DumpSize(x, D)
-  self:DumpBlock(self:from_int(x), D)
+  self:DumpBlock(self:from_int(x, cfg.size_t_size), D)
 end
 
 ------------------------------------------------------------------------
index 1e0c1cadb2c3c49520a6dfad86716a6cf2998658..5406a00c84a847afc626fef147aee1b6d56ca394 100644 (file)
@@ -18,7 +18,7 @@ PLATFORMS = macosx mingw linux
 
 TARGET_LUA_PATH  = /tmp/metalua
 TARGET_LUA_CPATH = $(TARGET_LUA_PATH)
-TARGET_BIN_PATH  = /tmp/bin
+TARGET_BIN_PATH  = $(TARGET_LUA_PATH)/bin
 
 #########################################################
 # Lua VM settings
index 8256462bc0d77f67bbbcffbc7d22ebcba0dd89ee..b6445f5d0a84cfcf2099f9a62e9ad8208272a6e8 100644 (file)
@@ -99,15 +99,15 @@ linux:
        $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses"
 
 macosx:
-       $(MAKE) all MYCFLAGS=-DLUA_USE_MACOSX
-# use this on Mac OS X 10.4
-#      $(MAKE) all MYCFLAGS="-DLUA_USE_MACOSX -DLUA_USE_READLINE" MYLIBS="-lreadline"
+       $(MAKE) all MYCFLAGS="-DLUA_USE_MACOSX -DLUA_USE_READLINE" MYLIBS="-lreadline"
+# use this on Mac OS X 10.3-
+#      $(MAKE) all MYCFLAGS=-DLUA_USE_MACOSX
 
 mingw:
        $(MAKE) "LUA_A=lua51.dll" "LUA_T=lua.exe" \
        "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \
        "MYCFLAGS=-DLUA_BUILD_AS_DLL" "MYLIBS=" "MYLDFLAGS=-s" lua.exe
-       $(MAKE) "LUA_A=lua51.dll" "LUAC_T=luac.exe" "MYCFLAGS=-DLUA_BUILD_AS_DLL" "MYLIBS=" "MYLDFLAGS=-s" luac.exe
+       $(MAKE) "LUAC_T=luac.exe" luac.exe
 
 posix:
        $(MAKE) all MYCFLAGS=-DLUA_USE_POSIX
@@ -148,8 +148,7 @@ llex.o: llex.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h ltm.h \
 lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h
 lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
   ltm.h lzio.h lmem.h ldo.h
-loadlib.o: loadlib.c lauxlib.h lua.h luaconf.h lobject.h llimits.h \
-  lualib.h
+loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h
 lobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \
   ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h
 lopcodes.o: lopcodes.c lopcodes.h llimits.h lua.h luaconf.h
index 7c532b8b1b36f851a6215f4a17a76033cc26e0a8..d7e8931e450099b1f0860068eb57928175ffddff 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 2.55 2006/06/07 12:37:17 roberto Exp $
+** $Id: lapi.c,v 2.55.1.3 2008/01/03 15:20:39 roberto Exp $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -123,6 +123,11 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
 }
 
 
+LUA_API void lua_setlevel (lua_State *from, lua_State *to) {
+  to->nCcalls = from->nCcalls;
+}
+
+
 LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {
   lua_CFunction old;
   lua_lock(L);
@@ -749,7 +754,7 @@ LUA_API int lua_setfenv (lua_State *L, int idx) {
       res = 0;
       break;
   }
-  luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1));
+  if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1));
   L->top--;
   lua_unlock(L);
   return res;
index 9d1d435649c7431281e56b852364e697f5a75bf8..2c3fab244ef9e7c4940dbd241885ac48bca4e005 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.h,v 2.2 2005/04/25 19:24:10 roberto Exp $
+** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Auxiliary functions from Lua API
 ** See Copyright Notice in lua.h
 */
index 96a6b85237ac7d3a98f8e230acaa2f40ac43db3a..10f14e2c088e60085bdf186c20c9b178c5fad2b4 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lauxlib.c,v 1.159 2006/03/21 19:31:09 roberto Exp $
+** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */
@@ -244,7 +244,7 @@ LUALIB_API void luaI_openlib (lua_State *L, const char *libname,
   if (libname) {
     int size = libsize(l);
     /* check whether lib already exists */
-    luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", size);
+    luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1);
     lua_getfield(L, -1, libname);  /* get _LOADED[libname] */
     if (!lua_istable(L, -1)) {  /* not found? */
       lua_pop(L, 1);  /* remove previous result */
@@ -535,7 +535,7 @@ static const char *getF (lua_State *L, void *ud, size_t *size) {
     return "\n";
   }
   if (feof(lf->f)) return NULL;
-  *size = fread(lf->buff, 1, LUAL_BUFFERSIZE, lf->f);
+  *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f);
   return (*size > 0) ? lf->buff : NULL;
 }
 
@@ -570,9 +570,8 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
     while ((c = getc(lf.f)) != EOF && c != '\n') ;  /* skip first line */
     if (c == '\n') c = getc(lf.f);
   }
-  if (c == LUA_SIGNATURE[0] && lf.f != stdin) {  /* binary file? */
-    fclose(lf.f);
-    lf.f = fopen(filename, "rb");  /* reopen in binary mode */
+  if (c == LUA_SIGNATURE[0] && filename) {  /* binary file? */
+    lf.f = freopen(filename, "rb", lf.f);  /* reopen in binary mode */
     if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
     /* skip eventual `#!...' */
    while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ;
@@ -581,7 +580,7 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
   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 (filename) fclose(lf.f);  /* close file (even in case of errors) */
   if (readstatus) {
     lua_settop(L, fnameindex);  /* ignore results from `lua_load' */
     return errfile(L, "read", fnameindex);
index 1f3430863e46392f3f914106a3f93ca7639d4526..34258235dbebff581b08a09d3acff87204cd5406 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lauxlib.h,v 1.88 2006/04/12 20:31:15 roberto Exp $
+** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */
index 147a727e06e6b077764490ab68334b1f920b5736..eb06bcef867934048a46822c49ad3431b2fba7a9 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lbaselib.c,v 1.191a 2006/06/02 15:34:00 roberto Exp $
+** $Id: lbaselib.c,v 1.191.1.4 2008/01/20 13:53:22 roberto Exp $
 ** Basic library
 ** See Copyright Notice in lua.h
 */
@@ -477,15 +477,52 @@ static const luaL_Reg base_funcs[] = {
 ** =======================================================
 */
 
+#define CO_RUN 0       /* running */
+#define CO_SUS 1       /* suspended */
+#define CO_NOR 2       /* 'normal' (it resumed another coroutine) */
+#define CO_DEAD        3
+
+static const char *const statnames[] =
+    {"running", "suspended", "normal", "dead"};
+
+static int costatus (lua_State *L, lua_State *co) {
+  if (L == co) return CO_RUN;
+  switch (lua_status(co)) {
+    case LUA_YIELD:
+      return CO_SUS;
+    case 0: {
+      lua_Debug ar;
+      if (lua_getstack(co, 0, &ar) > 0)  /* does it have frames? */
+        return CO_NOR;  /* it is running */
+      else if (lua_gettop(co) == 0)
+          return CO_DEAD;
+      else
+        return CO_SUS;  /* initial state */
+    }
+    default:  /* some error occured */
+      return CO_DEAD;
+  }
+}
+
+
+static int luaB_costatus (lua_State *L) {
+  lua_State *co = lua_tothread(L, 1);
+  luaL_argcheck(L, co, 1, "coroutine expected");
+  lua_pushstring(L, statnames[costatus(L, co)]);
+  return 1;
+}
+
+
 static int auxresume (lua_State *L, lua_State *co, int narg) {
-  int status;
+  int status = costatus(L, co);
   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");
+  if (status != CO_SUS) {
+    lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]);
     return -1;  /* error flag */
   }
   lua_xmove(L, co, narg);
+  lua_setlevel(L, co);
   status = lua_resume(co, narg);
   if (status == 0 || status == LUA_YIELD) {
     int nres = lua_gettop(co);
@@ -556,39 +593,10 @@ static int luaB_yield (lua_State *L) {
 }
 
 
-static int luaB_costatus (lua_State *L) {
-  lua_State *co = lua_tothread(L, 1);
-  luaL_argcheck(L, co, 1, "coroutine expected");
-  if (L == co) lua_pushliteral(L, "running");
-  else {
-    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 int luaB_corunning (lua_State *L) {
   if (lua_pushthread(L))
-    return 0;  /* main thread is not a coroutine */
-  else
-    return 1;
+    lua_pushnil(L);  /* main thread is not a coroutine */
+  return 1;
 }
 
 
index 9ce515ab648b008d4f39370f0010b39cda3a0aa5..cff626b7fa6df8307dad49803a0236ebc71f336f 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 2.25a 2006/03/21 19:28:49 roberto Exp $
+** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -699,7 +699,7 @@ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
   e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
   switch (op) {
     case OPR_MINUS: {
-      if (e->k == VK)
+      if (!isnumeral(e))
         luaK_exp2anyreg(fs, e);  /* cannot operate on non-numeric constants */
       codearith(fs, OP_UNM, e, &e2);
       break;
index c02cb2b726f86b29dc1f7205f1e44f3332ee1c41..b941c607212bf5255be169d202af6617b5a99ed7 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.h,v 1.48 2006/03/21 19:28:03 roberto Exp $
+** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
index 26a19b6a6f6f04d9ee74dc49c32608feadbfca38..67de1222a948ca2e20e078d35e2e497bf833a986 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: ldblib.c,v 1.104 2005/12/29 15:32:11 roberto Exp $
+** $Id: ldblib.c,v 1.104.1.3 2008/01/21 13:11:21 roberto Exp $
 ** Interface from Lua to its debug API
 ** See Copyright Notice in lua.h
 */
@@ -255,24 +255,25 @@ static void gethooktable (lua_State *L) {
 
 
 static int db_sethook (lua_State *L) {
-  int arg;
+  int arg, mask, count;
+  lua_Hook func;
   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 */
+    func = NULL; mask = 0; count = 0;  /* turn off hooks */
   }
   else {
     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);
+    count = luaL_optint(L, arg+3, 0);
+    func = hookf; mask = makemask(smask, count);
   }
-  gethooktable(L1);
-  lua_pushlightuserdata(L1, L1);
+  gethooktable(L);
+  lua_pushlightuserdata(L, 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 */
+  lua_rawset(L, -3);  /* set new hook */
+  lua_pop(L, 1);  /* remove hook table */
+  lua_sethook(L1, func, mask, count);  /* set hooks */
   return 0;
 }
 
@@ -286,11 +287,10 @@ static int db_gethook (lua_State *L) {
   if (hook != NULL && hook != hookf)  /* external hook? */
     lua_pushliteral(L, "external hook");
   else {
-    gethooktable(L1);
-    lua_pushlightuserdata(L1, L1);
-    lua_rawget(L1, -2);   /* get hook */
-    lua_remove(L1, -2);  /* remove hook table */
-    lua_xmove(L1, L, 1);
+    gethooktable(L);
+    lua_pushlightuserdata(L, L1);
+    lua_rawget(L, -2);   /* get hook */
+    lua_remove(L, -2);  /* remove hook table */
   }
   lua_pushstring(L, unmakemask(mask, buff));
   lua_pushinteger(L, lua_gethookcount(L1));
index 9c8bdf2fb90cadb3388772b9a6a5c21f84fd718d..9eac4a9b4161dc8d8a15f553ba3e1dd8cae484dd 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.c,v 2.29a 2005/12/22 16:19:56 roberto Exp $
+** $Id: ldebug.c,v 2.29.1.3 2007/12/28 15:32:23 roberto Exp $
 ** Debug Interface
 ** See Copyright Notice in lua.h
 */
@@ -563,8 +563,8 @@ void luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
 
 
 void luaG_concaterror (lua_State *L, StkId p1, StkId p2) {
-  if (ttisstring(p1)) p1 = p2;
-  lua_assert(!ttisstring(p1));
+  if (ttisstring(p1) || ttisnumber(p1)) p1 = p2;
+  lua_assert(!ttisstring(p1) && !ttisnumber(p1));
   luaG_typeerror(L, p1, "concatenate");
 }
 
index 9c76aa10f0a2bdb26f1c89e05609ba9556a8114e..ba28a97248eb29d9a7f1c9af4ed6e49d30574df9 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.h,v 2.3 2005/04/25 19:24:10 roberto Exp $
+** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Auxiliary functions from Debug Interface module
 ** See Copyright Notice in lua.h
 */
index ab86fb70e8d21000fcf449ea23fc4af13a30484f..8de05f728e767e2d38ae4adf3d4f35134e16608b 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 2.38 2006/06/05 19:36:14 roberto Exp $
+** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -83,7 +83,7 @@ static void resetstack (lua_State *L, int status) {
   L->base = L->ci->base;
   luaF_close(L, L->base);  /* close eventual pending closures */
   luaD_seterrorobj(L, status, L->base);
-  L->nCcalls = 0;
+  L->nCcalls = L->baseCcalls;
   L->allowhook = 1;
   restore_stack_limit(L);
   L->errfunc = 0;
@@ -332,7 +332,7 @@ 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 (f_isLua(L->ci)) {  /* Lua function? */
-    while (L->ci->tailcalls--)  /* call hook for eventual tail calls */
+    while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */
       luaD_callhook(L, LUA_HOOKTAILRET, -1);
   }
   return restorestack(L, fr);
@@ -417,22 +417,24 @@ static int resume_error (lua_State *L, const char *msg) {
 LUA_API int lua_resume (lua_State *L, int nargs) {
   int status;
   lua_lock(L);
-  if (L->status != LUA_YIELD) {
-    if (L->status != 0)
-      return resume_error(L, "cannot resume dead coroutine");
-    else if (L->ci != L->base_ci)
+  if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci))
       return resume_error(L, "cannot resume non-suspended coroutine");
-  }
+  if (L->nCcalls >= LUAI_MAXCCALLS)
+    return resume_error(L, "C stack overflow");
   luai_userstateresume(L, nargs);
-  lua_assert(L->errfunc == 0 && L->nCcalls == 0);
+  lua_assert(L->errfunc == 0);
+  L->baseCcalls = ++L->nCcalls;
   status = luaD_rawrunprotected(L, resume, L->top - nargs);
   if (status != 0) {  /* error? */
     L->status = cast_byte(status);  /* mark thread as `dead' */
     luaD_seterrorobj(L, status, L->top);
     L->ci->top = L->top;
   }
-  else
+  else {
+    lua_assert(L->nCcalls == L->baseCcalls);
     status = L->status;
+  }
+  --L->nCcalls;
   lua_unlock(L);
   return status;
 }
@@ -441,7 +443,7 @@ LUA_API int lua_resume (lua_State *L, int nargs) {
 LUA_API int lua_yield (lua_State *L, int nresults) {
   luai_userstateyield(L, nresults);
   lua_lock(L);
-  if (L->nCcalls > 0)
+  if (L->nCcalls > L->baseCcalls)
     luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");
   L->base = L->top - nresults;  /* protect stack slots below */
   L->status = LUA_YIELD;
index b2de92bb807f4e384d0647bcc56cf1a221153b7e..98fddac59fbd84c8e49ab3da8033bed30ca8362b 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.h,v 2.7 2005/08/24 16:15:49 roberto Exp $
+** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
index f08277d3ac440a48a3f771113729f39f492e57cc..c9d3d4870f4d915a46e4f98d88a6af735325647b 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: ldump.c,v 1.15 2006/02/16 15:53:49 lhf Exp $
+** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $
 ** save precompiled Lua chunks
 ** See Copyright Notice in lua.h
 */
index 05bd5ff50fa1ffe39c3c62fa95402884e091d313..813e88f5831bb9cfb6f5dabfae930df30231fa67 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lfunc.c,v 2.12a 2005/12/22 16:19:56 roberto Exp $
+** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $
 ** Auxiliary functions to manipulate prototypes and closures
 ** See Copyright Notice in lua.h
 */
index 2e02419bd6bc3f3efd67a007dfbb40f3f3300459..a68cf5151cba3a0fff09f22943ef1665ab9cf7f2 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lfunc.h,v 2.4 2005/04/25 19:24:10 roberto Exp $
+** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Auxiliary functions to manipulate prototypes and closures
 ** See Copyright Notice in lua.h
 */
index 2d24a127ac6312679cd93000a2a65f1d86c159e5..d9e0b78294e0cd28f998984b487ae7c544d7071f 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 2.38 2006/05/24 14:34:06 roberto Exp $
+** $Id: lgc.c,v 2.38.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
index 5f69acb1e3b8ecf2717e8f0acc687a6527b8d20f..5a8dc605b319f5e1320f5b4be8f9156312b0327e 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.h,v 2.15 2005/08/24 16:15:49 roberto Exp $
+** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
index 483d9c8c282e13eb129d2919adc71fafd8318a17..c1f90dfab7156ce1e120d95b79e356395a8c113b 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: linit.c,v 1.14 2005/12/29 15:32:11 roberto Exp $
+** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Initialization of libraries for lua.c
 ** See Copyright Notice in lua.h
 */
index be60972ca8dec35c35c01af4eb8d61de1a2c2ce5..e79ed1cb2e216a412c74833a522863c6761b4af6 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: liolib.c,v 2.73 2006/05/08 20:14:16 roberto Exp $
+** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 roberto Exp $
 ** Standard I/O (and system) library
 ** See Copyright Notice in lua.h
 */
@@ -51,7 +51,7 @@ static void fileerror (lua_State *L, int arg, const char *filename) {
 }
 
 
-#define topfile(L)     ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))
+#define tofilep(L)     ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))
 
 
 static int io_type (lua_State *L) {
@@ -70,7 +70,7 @@ static int io_type (lua_State *L) {
 
 
 static FILE *tofile (lua_State *L) {
-  FILE **f = topfile(L);
+  FILE **f = tofilep(L);
   if (*f == NULL)
     luaL_error(L, "attempt to use a closed file");
   return *f;
@@ -93,19 +93,31 @@ static FILE **newfile (lua_State *L) {
 
 
 /*
-** this function has a separated environment, which defines the
-** correct __close for 'popen' files
+** function to (not) close the standard files stdin, stdout, and stderr
+*/
+static int io_noclose (lua_State *L) {
+  lua_pushnil(L);
+  lua_pushliteral(L, "cannot close standard file");
+  return 2;
+}
+
+
+/*
+** function to close 'popen' files
 */
 static int io_pclose (lua_State *L) {
-  FILE **p = topfile(L);
+  FILE **p = tofilep(L);
   int ok = lua_pclose(L, *p);
   *p = NULL;
   return pushresult(L, ok, NULL);
 }
 
 
+/*
+** function to close regular files
+*/
 static int io_fclose (lua_State *L) {
-  FILE **p = topfile(L);
+  FILE **p = tofilep(L);
   int ok = (fclose(*p) == 0);
   *p = NULL;
   return pushresult(L, ok, NULL);
@@ -128,18 +140,18 @@ static int io_close (lua_State *L) {
 
 
 static int io_gc (lua_State *L) {
-  FILE *f = *topfile(L);
-  /* ignore closed files and standard files */
-  if (f != NULL && f != stdin && f != stdout && f != stderr)
+  FILE *f = *tofilep(L);
+  /* ignore closed files */
+  if (f != NULL)
     aux_close(L);
   return 0;
 }
 
 
 static int io_tostring (lua_State *L) {
-  FILE *f = *topfile(L);
+  FILE *f = *tofilep(L);
   if (f == NULL)
-    lua_pushstring(L, "file (closed)");
+    lua_pushliteral(L, "file (closed)");
   else
     lua_pushfstring(L, "file (%p)", f);
   return 1;
@@ -155,6 +167,10 @@ static int io_open (lua_State *L) {
 }
 
 
+/*
+** this function has a separated environment, which defines the
+** correct __close for 'popen' files
+*/
 static int io_popen (lua_State *L) {
   const char *filename = luaL_checkstring(L, 1);
   const char *mode = luaL_optstring(L, 2, "r");
@@ -280,7 +296,7 @@ static int read_line (lua_State *L, FILE *f) {
     char *p = luaL_prepbuffer(&b);
     if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) {  /* eof? */
       luaL_pushresult(&b);  /* close buffer */
-      return (lua_strlen(L, -1) > 0);  /* check whether read something */
+      return (lua_objlen(L, -1) > 0);  /* check whether read something */
     }
     l = strlen(p);
     if (l == 0 || p[l-1] != '\n')
@@ -308,7 +324,7 @@ static int read_chars (lua_State *L, FILE *f, size_t n) {
     n -= nr;  /* still have to read `n' chars */
   } while (n > 0 && nr == rlen);  /* until end of count or eof */
   luaL_pushresult(&b);  /* close buffer */
-  return (n == 0 || lua_strlen(L, -1) > 0);
+  return (n == 0 || lua_objlen(L, -1) > 0);
 }
 
 
@@ -502,31 +518,36 @@ static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {
     lua_pushvalue(L, -1);
     lua_rawseti(L, LUA_ENVIRONINDEX, k);
   }
-  lua_setfield(L, -2, fname);
+  lua_pushvalue(L, -2);  /* copy environment */
+  lua_setfenv(L, -2);  /* set it */
+  lua_setfield(L, -3, fname);
+}
+
+
+static void newfenv (lua_State *L, lua_CFunction cls) {
+  lua_createtable(L, 0, 1);
+  lua_pushcfunction(L, cls);
+  lua_setfield(L, -2, "__close");
 }
 
 
 LUALIB_API int luaopen_io (lua_State *L) {
   createmeta(L);
   /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */
-  lua_createtable(L, 2, 1);
+  newfenv(L, io_fclose);
   lua_replace(L, LUA_ENVIRONINDEX);
   /* open library */
   luaL_register(L, LUA_IOLIBNAME, iolib);
   /* create (and set) default files */
+  newfenv(L, io_noclose);  /* close function for default files */
   createstdfile(L, stdin, IO_INPUT, "stdin");
   createstdfile(L, stdout, IO_OUTPUT, "stdout");
   createstdfile(L, stderr, 0, "stderr");
-  /* create environment for 'popen' */
+  lua_pop(L, 1);  /* pop environment for default files */
   lua_getfield(L, -1, "popen");
-  lua_createtable(L, 0, 1);
-  lua_pushcfunction(L, io_pclose);
-  lua_setfield(L, -2, "__close");
-  lua_setfenv(L, -2);
+  newfenv(L, io_pclose);  /* create environment for 'popen' */
+  lua_setfenv(L, -2);  /* set fenv for 'popen' */
   lua_pop(L, 1);  /* pop 'popen' */
-  /* set default close function */
-  lua_pushcfunction(L, io_fclose);
-  lua_setfield(L, LUA_ENVIRONINDEX, "__close");
   return 1;
 }
 
index 1c07cad9bb67b91c85bfcb0723e2660523e6ca4b..6dc319358c0f76a88dcc545e8c5375f85f7a569c 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: llex.c,v 2.20 2006/03/09 18:14:31 roberto Exp $
+** $Id: llex.c,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Lexical Analyzer
 ** See Copyright Notice in lua.h
 */
index ff07e83d3184f037873220da421278b74f0e4f0e..a9201cee484750962a06a2691df2eec684ac4115 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: llex.h,v 1.58 2006/03/23 18:23:32 roberto Exp $
+** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Lexical Analyzer
 ** See Copyright Notice in lua.h
 */
index b03221aeec2ac6144225025d1eecb91ef2ad7f8e..ca8dcb72244bae473d27e605395b17a7d95c9c1c 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: llimits.h,v 1.69 2005/12/27 17:12:00 roberto Exp $
+** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Limits, basic types, and some other `installation-dependent' definitions
 ** See Copyright Notice in lua.h
 */
index d181a7319438f2adef703c3b5c0779134c78a7eb..441fbf736c2be400f4bf68e71d4c4a2591e71f55 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lmathlib.c,v 1.67 2005/08/26 17:36:32 roberto Exp $
+** $Id: lmathlib.c,v 1.67.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Standard mathematical library
 ** See Copyright Notice in lua.h
 */
index cef2bc5f8513fa99623cb00699586e9a18e187b7..ae7d8c965f6e996e77ab51bb7598d4f544a0e539 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lmem.c,v 1.70 2005/12/26 13:35:47 roberto Exp $
+** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Interface to Memory Manager
 ** See Copyright Notice in lua.h
 */
index 19df1fbb6c90f182bc27286d7c482f44605baf78..7c2dcb32207a0438684eb0566ce769f47d895cf4 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lmem.h,v 1.31 2005/04/25 19:24:10 roberto Exp $
+** $Id: lmem.h,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Interface to Memory Manager
 ** See Copyright Notice in lua.h
 */
index 808368ba4312cc63cb5708b93344c733777f84dd..d955f3ef4125dddba28e54ac0316f288fe7855fe 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: loadlib.c,v 1.54a 2006/07/03 20:16:49 roberto Exp $
+** $Id: loadlib.c,v 1.52.1.2 2007/12/28 14:58:43 roberto Exp $
 ** Dynamic library loader for Lua
 ** See Copyright Notice in lua.h
 **
index acde82ccdf16365bc28b7fb2f202d09fc4a19598..4ff50732a4a990159b232548b634ee2cd9749c42 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.c,v 2.22 2006/02/10 17:43:52 roberto Exp $
+** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Some generic functions over Lua objects
 ** See Copyright Notice in lua.h
 */
index 8ce4405b6aeaa550d6cbe3a51a65e43e693118f5..e7199dfc689e7b210b378bdb34fb9b5677ca19f2 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 2.20 2006/01/18 11:37:34 roberto Exp $
+** $Id: lobject.h,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */
index bf9cd522c260aa7a36ff76e19fc1a330d19b6e9c..4cc745230b79f8c3d916dc992cd5b4ea4352d274 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.c,v 1.37 2005/11/08 19:45:36 roberto Exp $
+** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $
 ** See Copyright Notice in lua.h
 */
 
index 48105f1e72268f095fadf5570a01994e0b02933a..41224d6ee14daca139e35f2fa0c41c92a8bc99c8 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.h,v 1.125 2006/03/14 19:04:44 roberto Exp $
+** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */
index fdda47414d0691bb4704f673aa31170604f4a4a5..da06a572acf61277143a506475c4e642e4b92a55 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: loslib.c,v 1.20 2006/09/19 13:57:08 roberto Exp $
+** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $
 ** Standard Operating System library
 ** See Copyright Notice in lua.h
 */
@@ -215,7 +215,6 @@ static int os_setlocale (lua_State *L) {
 
 static int os_exit (lua_State *L) {
   exit(luaL_optint(L, 1, EXIT_SUCCESS));
-  return 0;  /* to avoid warnings */
 }
 
 static const luaL_Reg syslib[] = {
index 6c473c41d2f6f55155ecedb218e05771b2beab06..1e2a9a88b796ae194c6184f861af8774e1e82337 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 2.42a 2006/06/05 15:57:59 roberto Exp $
+** $Id: lparser.c,v 2.42.1.3 2007/12/28 15:32:23 roberto Exp $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */
@@ -938,6 +938,8 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
     primaryexp(ls, &nv.v);
     if (nv.v.k == VLOCAL)
       check_conflict(ls, lh, &nv.v);
+    luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls,
+                    "variables in assignment");
     assignment(ls, &nv, nvars+1);
   }
   else {  /* assignment -> `=' explist1 */
index e5b5b57e850b13f1f9bc6421b553813b87dcfcd8..18836afd1cdf9af6f1c00e2cda41d973694aa3ad 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.h,v 1.57 2006/03/09 18:14:31 roberto Exp $
+** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */
index 4bcb7594ce8e53467452ac06db5f88d59664bab0..4313b83a0c7cbdcdacbe57f0f2bfe30122b241d6 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.c,v 2.36 2006/05/24 14:15:50 roberto Exp $
+** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -93,7 +93,7 @@ static void preinit_state (lua_State *L, global_State *g) {
   resethookcount(L);
   L->openupval = NULL;
   L->size_ci = 0;
-  L->nCcalls = 0;
+  L->nCcalls = L->baseCcalls = 0;
   L->status = 0;
   L->base_ci = L->ci = NULL;
   L->savedpc = NULL;
@@ -205,7 +205,7 @@ LUA_API void lua_close (lua_State *L) {
   do {  /* repeat until no more errors */
     L->ci = L->base_ci;
     L->base = L->top = L->ci->base;
-    L->nCcalls = 0;
+    L->nCcalls = L->baseCcalls = 0;
   } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0);
   lua_assert(G(L)->tmudata == NULL);
   luai_userstateclose(L);
index d296a4cab99e1cb1ec5f09bc0cd1bfc74e1cd5cc..3bc575b6bc8cdef8286ea4d8d539a4ee4fe5a180 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 2.24 2006/02/06 18:27:59 roberto Exp $
+** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -112,6 +112,7 @@ struct lua_State {
   int stacksize;
   int size_ci;  /* size of array `base_ci' */
   unsigned short nCcalls;  /* number of nested C calls */
+  unsigned short baseCcalls;  /* nested C calls when resuming coroutine */
   lu_byte hookmask;
   lu_byte allowhook;
   int basehookcount;
index 4319930c96d07e61fe98b697b87c538280cf38c9..49113151cc709aa35f469a82a004b37d850d4bf5 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.c,v 2.8 2005/12/22 16:19:56 roberto Exp $
+** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $
 ** String table (keeps all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
index 1d2e91ea13a31bcfbdbee4c63dc17d1e99e9f8e4..73a2ff8b380d6453a2d6caa8e80c7ed05f081804 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.h,v 1.43 2005/04/25 19:24:10 roberto Exp $
+** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $
 ** String table (keep all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
index fc7ae4894add43e969f59aa5361d1d1965cd35bb..ca333ba1688f1abbe433de4073fe776b99b0471b 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lstrlib.c,v 1.132a 2006/04/26 20:41:19 roberto Exp $
+** $Id: lstrlib.c,v 1.132.1.3 2007/12/28 15:32:23 roberto Exp $
 ** Standard library for string operations and pattern-matching
 ** See Copyright Notice in lua.h
 */
@@ -629,10 +629,6 @@ static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
       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);
@@ -648,11 +644,15 @@ static int str_gsub (lua_State *L) {
   size_t srcl;
   const char *src = luaL_checklstring(L, 1, &srcl);
   const char *p = luaL_checkstring(L, 2);
+  int  tr = lua_type(L, 3);
   int max_s = luaL_optint(L, 4, srcl+1);
   int anchor = (*p == '^') ? (p++, 1) : 0;
   int n = 0;
   MatchState ms;
   luaL_Buffer b;
+  luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
+                   tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3,
+                      "string/function/table expected");
   luaL_buffinit(L, &b);
   ms.L = L;
   ms.src_init = src;
index bc91cacd637fe4563637f8c02740dc57a9cf50de..ec84f4fabc513b7c765e46bda0432b571c13fb1a 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.c,v 2.32 2006/01/18 11:49:02 roberto Exp $
+** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */
@@ -84,8 +84,8 @@ static const Node dummynode_ = {
 static Node *hashnum (const Table *t, lua_Number n) {
   unsigned int a[numints];
   int i;
-  n += 1;  /* normalize number (avoid -0) */
-  lua_assert(sizeof(a) <= sizeof(n));
+  if (luai_numeq(n, 0))  /* avoid problems with -0 */
+    return gnode(t, 0);
   memcpy(a, &n, sizeof(a));
   for (i = 1; i < numints; i++) a[0] += a[i];
   return hashmod(t, a[0]);
index 09193cdbe048c9a19b8277f9c2bfae4af98591cf..f5b9d5ead0f4a44fba1f800f5c4d604beabdbe73 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.h,v 2.10 2006/01/10 13:13:06 roberto Exp $
+** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */
index 453b23b378bc5a215905cc974a9d981827b989a8..06f1c37be17c5f67371c59a650f8fb1f8c269a33 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: ltablib.c,v 1.38 2005/10/23 17:38:15 roberto Exp $
+** $Id: ltablib.c,v 1.38.1.2 2007/12/28 15:32:23 roberto Exp $
 ** Library for Table Manipulation
 ** See Copyright Notice in lua.h
 */
@@ -118,7 +118,8 @@ static int tinsert (lua_State *L) {
 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' */
+  if (!(1 <= pos && pos <= e))  /* position is outside bounds? */
+   return 0;  /* nothing to remove */
   luaL_setn(L, 1, e - 1);  /* t.n = n-1 */
   lua_rawgeti(L, 1, pos);  /* result = t[pos] */
   for ( ;pos<e; pos++) {
index 097b815ad3a58f51d19bcc3758dd6f04625bd72f..c27f0f6fab8561f1097a64a6eed1b7785921c74b 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.c,v 2.8 2006/01/10 12:50:00 roberto Exp $
+** $Id: ltm.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */
index 866c79668d89673f350d37d0408b37bd94965448..64343b781b6498930c30abc8f56ce2f7c5ede1ac 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.h,v 2.6 2005/06/06 13:30:25 roberto Exp $
+** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */
index 5cee7fa9f0b0d0fb4b8df78739ded11fd5cc865f..3a46609328cb015b1aa442770e7e1c400b9adb2b 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lua.c,v 1.160 2006/06/02 15:34:00 roberto Exp $
+** $Id: lua.c,v 1.160.1.2 2007/12/28 15:32:23 roberto Exp $
 ** Lua stand-alone interpreter
 ** See Copyright Notice in lua.h
 */
@@ -74,6 +74,8 @@ static int report (lua_State *L, int status) {
 
 
 static int traceback (lua_State *L) {
+  if (!lua_isstring(L, 1))  /* 'message' not a string? */
+    return 1;  /* keep it intact */
   lua_getfield(L, LUA_GLOBALSINDEX, "debug");
   if (!lua_istable(L, -1)) {
     lua_pop(L, 1);
@@ -144,7 +146,7 @@ static int dostring (lua_State *L, const char *s, const char *name) {
 static int dolibrary (lua_State *L, const char *name) {
   lua_getglobal(L, "require");
   lua_pushstring(L, name);
-  return report(L, lua_pcall(L, 1, 0, 0));
+  return report(L, docall(L, 1, 1));
 }
 
 
index 2865a7fae96dc1f891272e1f533a90380f5f6d58..5bc97b746fd20d62551d839fd11d55c6fa1f8a53 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lua.h,v 1.218a 2006/06/02 15:34:00 roberto Exp $
+** $Id: lua.h,v 1.218.1.4 2008/01/03 15:41:15 roberto Exp $
 ** Lua - An Extensible Extension Language
 ** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
 ** See Copyright Notice at the end of this file
@@ -17,9 +17,9 @@
 
 
 #define LUA_VERSION    "Lua 5.1"
-#define LUA_RELEASE    "Lua 5.1.2"
+#define LUA_RELEASE    "Lua 5.1.3"
 #define LUA_VERSION_NUM        501
-#define LUA_COPYRIGHT  "Copyright (C) 1994-2007 Lua.org, PUC-Rio"
+#define LUA_COPYRIGHT  "Copyright (C) 1994-2008 Lua.org, PUC-Rio"
 #define LUA_AUTHORS    "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
 
 
@@ -294,6 +294,9 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
 #define lua_Chunkwriter                lua_Writer
 
 
+/* hack */
+LUA_API void lua_setlevel      (lua_State *from, lua_State *to);
+
 
 /*
 ** {======================================================================
@@ -359,7 +362,7 @@ struct lua_Debug {
 
 
 /******************************************************************************
-* Copyright (C) 1994-2007 Lua.org, PUC-Rio.  All rights reserved.
+* Copyright (C) 1994-2008 Lua.org, PUC-Rio.  All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
index 60a3e19dc07d953a6c017a4bfa12194f67bbadc1..eb2f5a1f71176c19d7fb293ef4924c2dcbf5e9cd 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: luaconf.h,v 1.82a 2006/04/10 18:27:23 roberto Exp $
+** $Id: luaconf.h,v 1.82.1.6 2008/01/18 17:07:48 roberto Exp $
 ** Configuration file for Lua
 ** See Copyright Notice in lua.h
 */
 ** (versions 3.2 and later) mark them as "hidden" to optimize access
 ** when Lua is compiled as a shared library.
 */
-#if 1 /* Metalua: export internal symbols needed by Pluto. */
-#  define LUAI_FUNC LUA_API
-#  define LUAI_DATA LUA_API
-#else /* Metalua: Original version, disabled */
-#  if defined(luaall_c)
-#    define LUAI_FUNC  static
-#    define LUAI_DATA  /* empty */
-#  elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \
-        defined(__ELF__)
-#    define LUAI_FUNC  __attribute__((visibility("hidden"))) extern
-#    define LUAI_DATA  LUAI_FUNC
-#  else
-#    define LUAI_FUNC  extern
-#    define LUAI_DATA  extern
-#  endif
+#if defined(luaall_c)
+#define LUAI_FUNC      static
+#define LUAI_DATA      /* empty */
+
+#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \
+      defined(__ELF__)
+#define LUAI_FUNC      __attribute__((visibility("hidden"))) extern
+#define LUAI_DATA      LUAI_FUNC
+
+#else
+#define LUAI_FUNC      extern
+#define LUAI_DATA      extern
 #endif
 
 
 ** functions. This limit is arbitrary; its only purpose is to stop C
 ** functions to consume unlimited stack space.
 */
-#define LUAI_MAXCSTACK 2048
+#define LUAI_MCS_AUX   ((int)(INT_MAX / (4*sizeof(LUA_NUMBER))))
+#define LUAI_MAXCSTACK (LUAI_MCS_AUX > SHRT_MAX ? SHRT_MAX : LUAI_MCS_AUX)
 
 
 
@@ -669,7 +667,7 @@ union luai_Cast { double l_d; long l_l; };
 */
 #if defined(LUA_USE_POPEN)
 
-#define lua_popen(L,c,m)       ((void)L, popen(c,m))
+#define lua_popen(L,c,m)       ((void)L, fflush(NULL), popen(c,m))
 #define lua_pclose(L,file)     ((void)L, (pclose(file) != -1))
 
 #elif defined(LUA_WIN)
index 0c76232c0dd03737542483119723ebc2ae779c57..469417f6703eb65a4559188f4febabac1a2ce01c 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lualib.h,v 1.36 2005/12/27 17:12:00 roberto Exp $
+** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Lua standard libraries
 ** See Copyright Notice in lua.h
 */
index 7fc635eeb7bebb9ba08ca0151ce24bf0c0acb910..731c064553e24818eadb60e0771de46be2f06aee 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lundump.c,v 1.60 2006/02/16 15:53:49 lhf Exp $
+** $Id: lundump.c,v 2.7.1.2 2008/01/18 16:39:11 roberto Exp $
 ** load precompiled Lua chunks
 ** See Copyright Notice in lua.h
 */
@@ -29,6 +29,7 @@ typedef struct {
 
 #ifdef LUAC_TRUST_BINARIES
 #define IF(c,s)
+#define error(S,s)
 #else
 #define IF(c,s)                if (c) error(S,s)
 
@@ -47,6 +48,7 @@ static void error(LoadState* S, const char* why)
 static void LoadBlock(LoadState* S, void* b, size_t size)
 {
  size_t r=luaZ_read(S->Z,b,size);
+ UNUSED(r);
  IF (r!=0, "unexpected end");
 }
 
@@ -122,7 +124,7 @@ static void LoadConstants(LoadState* S, Proto* f)
        setsvalue2n(S->L,o,LoadString(S));
        break;
    default:
-       IF (1, "bad constant");
+       error(S,"bad constant");
        break;
   }
  }
index 58cca5d19083a235e835566f1867104f011aa70d..c80189dbffc65fa56de1ebc471ba07ac22407ad1 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lundump.h,v 1.40 2005/11/11 14:03:13 lhf Exp $
+** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $
 ** load precompiled Lua chunks
 ** See Copyright Notice in lua.h
 */
index 08802f440f33482e2d964049d8f3ad296422fb82..ee3256ab94deb67ee5fa24e35a0df095c7f8ae9d 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 2.63a 2006/06/05 15:58:59 roberto Exp $
+** $Id: lvm.c,v 2.63.1.3 2007/12/28 15:32:23 roberto Exp $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -61,11 +61,9 @@ static void traceexec (lua_State *L, const Instruction *pc) {
   lu_byte mask = L->hookmask;
   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);
-    }
+  if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) {
+    resethookcount(L);
+    luaD_callhook(L, LUA_HOOKCOUNT, -1);
   }
   if (mask & LUA_MASKLINE) {
     Proto *p = ci_func(L->ci)->l.p;
index 788423f8e31f8e9bcf30415584faaec768ea767a..bfe4f5678d0256150b9022a3ca2060fe9b963914 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.h,v 2.5 2005/08/22 18:54:49 roberto Exp $
+** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
index 5121ada8466e75cfe60cf9cde8282c30499892b8..293edd59b08f1e57b361b4cfb9ad63e384f14b1b 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lzio.c,v 1.31 2005/06/03 20:15:29 roberto Exp $
+** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $
 ** a generic input stream interface
 ** See Copyright Notice in lua.h
 */
index 8f403b8e74f5e4562328ebfa76f9c0ef4c77266d..51d695d8c1d5a26ba2146d5b1866c00c52771499 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lzio.h,v 1.21 2005/05/17 19:49:15 roberto Exp $
+** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $
 ** Buffered streams
 ** See Copyright Notice in lua.h
 */
index 76af4469d37e9f0a3eb12df71ffa622c0ba81dc5..6fe66f31e8610e262f8d8eb8f9f8f3884a32b5a5 100644 (file)
@@ -1,70 +1,83 @@
-set MLUALIB_TARGET=c:\tmp\mlualib\r
-set MSVCDIR=c:\msvc\vc98\bin\r
-md %MLUALIB_TARGET%\r
-\r
-:lua\r
-@REM Build lua51.dll, lua51.lib, lua.exe, luac.exe\r
-@REM Code taken straight from Lua's etc/luavs.bat\r
-cd lua\r
-%MSVCDIR%\cl /nologo /MD /O2 /W3 /c /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DLUA_BUILD_AS_DLL l*.c\r
-del lua.obj luac.obj\r
-%MSVCDIR%\link /nologo /DLL /out:lua51.dll l*.obj\r
-%MSVCDIR%\cl /nologo /MD /O2 /W3 /c /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DLUA_BUILD_AS_DLL lua.c\r
-%MSVCDIR%\link /nologo /out:lua.exe lua.obj lua51.lib\r
-%MSVCDIR%\cl /nologo /MD /O2 /W3 /c /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE l*.c print.c\r
-del lua.obj linit.obj lbaselib.obj ldblib.obj liolib.obj lmathlib.obj loslib.obj ltablib.obj lstrlib.obj loadlib.obj\r
-%MSVCDIR%\link /nologo /out:luac.exe *.obj\r
-del *.obj\r
-copy *.exe %MLUALIB_TARGET%\r
-copy *.lib %MLUALIB_TARGET%\r
-copy *.dll %MLUALIB_TARGET%\r
-cd ..\r
-\r
-:srclibs\r
-@REM copy libraries\r
-xcopy /E /Y lib %MLUALIB_TARGET%\r
-\r
-:binlibs\r
-@REM compile and install binary libs\r
-cd binlibs\r
-%MSVCDIR%\cl /nologo /LD /DLUA_BUILD_AS_DLL /DLUA_LIB /DBUILTIN_CAST /I..\lua bit.c ..\lua\lua51.lib\r
-%MSVCDIR%\cl /nologo /LD /DLUA_BUILD_AS_DLL /DLUA_LIB /I..\lua rings.c ..\lua\lua51.lib\r
-%MSVCDIR%\cl /nologo /LD /DLUA_BUILD_AS_DLL /DLUA_LIB /I..\lua pluto.c ..\lua\lua51.lib\r
-xcopy /Y rings.dll %MLUALIB_TARGET%\r
-xcopy /Y bit.dll   %MLUALIB_TARGET%\r
-xcopy /Y pluto.dll %MLUALIB_TARGET%\r
-cd ..\r
-\r
-:w32stub\r
-echo @set LUA_ROOT=%MLUALIB_TARGET%> %MLUALIB_TARGET%\metalua.bat\r
-type win32\metalua.bat >> %MLUALIB_TARGET%\metalua.bat\r
-\r
-:setenv\r
-@REM set Metalua environment\r
-echo set LUA_ROOT=%MLUALIB_TARGET% > mlua_setenv.bat\r
-echo set LUA_PATH=?.luac;?.lua;%MLUALIB_TARGET%\?.luac;%MLUALIB_TARGET%\?.lua >> mlua_setenv.bat\r
-echo set LUA_CPATH=?.dll;%MLUALIB_TARGET%\?.dll;%MLUALIB_TARGET%\?\linit.dll >> mlua_setenv.bat\r
-echo set LUA_MPATH=?.mlua;%MLUALIB_TARGET%\?.mlua >> mlua_setenv.bat\r
-echo set PATH=%MLUALIB_TARGET%;%PATH% >> mlua_setenv.bat\r
-CALL mlua_setenv.bat\r
-\r
-:compiler\r
-@REM Build the compiler *.lua libs\r
-cd compiler\r
-set LUA=..\lua\lua.exe\r
-set LUAC=..\lua\luac.exe\r
-%LUAC% -o bytecode.luac lopcodes.lua lcode.lua ldump.lua compile.lua\r
-%LUAC% -o mlp.luac lexer.lua gg.lua mlp_lexer.lua mlp_misc.lua mlp_table.lua mlp_meta.lua mlp_expr.lua mlp_stat.lua mlp_ext.lua\r
-xcopy /Y bytecode.luac %MLUALIB_TARGET%\r
-xcopy /Y mlp.luac %MLUALIB_TARGET%\r
-\r
-@REM Build the compiler *.mlua parts\r
-%LUA% bootstrap.lua mlc.mlua\r
-%LUA% bootstrap.lua metalua.mlua\r
-copy /Y mlc.luac %MLUALIB_TARGET%\r
-copy /Y metalua.luac %MLUALIB_TARGET%\r
-cd ..\r
-\r
-:compile_srclib\r
-@REM Precompile the .mlua files in the library\r
+set MLUALIB_TARGET=c:\tmp\mlualib
+
+set MSVCDIR=
+@set COMPILE=%MSVCDIR%cl /nologo /MD /O2 /W3 /c /D_CRT_SECURE_NO_DEPRECATE
+@set LINK=%MSVCDIR%link /nologo
+@set MT=%MSVCDIR%mt /nologo
+
+md %MLUALIB_TARGET%
+
+:lua
+@REM Build lua51.dll, lua51.lib, lua.exe, luac.exe
+@REM Code taken straight from Lua's etc/luavs.bat
+cd lua
+%COMPILE% /DLUA_BUILD_AS_DLL l*.c
+del lua.obj luac.obj
+%LINK% /DLL /out:lua51.dll l*.obj
+if exist lua51.dll.manifest^
+  %MT% -manifest lua51.dll.manifest -outputresource:lua51.dll;2
+%COMPILE% /DLUA_BUILD_AS_DLL lua.c
+%LINK% /out:lua.exe lua.obj lua51.lib
+if exist lua.exe.manifest^
+  %MT% -manifest lua.exe.manifest -outputresource:lua.exe
+%COMPILE% l*.c print.c
+del lua.obj linit.obj lbaselib.obj ldblib.obj liolib.obj lmathlib.obj^
+    loslib.obj ltablib.obj lstrlib.obj loadlib.obj
+%LINK% /out:luac.exe *.obj
+if exist luac.exe.manifest^
+  %MT% -manifest luac.exe.manifest -outputresource:luac.exe
+del *.obj *.manifest
+
+copy *.exe %MLUALIB_TARGET%
+copy *.lib %MLUALIB_TARGET%
+copy *.dll %MLUALIB_TARGET%
+cd ..
+
+:srclibs
+@REM copy libraries
+xcopy /E /Y lib %MLUALIB_TARGET%
+
+:binlibs
+@REM compile and install binary libs
+cd binlibs
+%COMPILE% /LD /DLUA_BUILD_AS_DLL /DLUA_LIB /DBUILTIN_CAST /I..\lua bit.c ..\lua\lua51.lib
+%COMPILE% /LD /DLUA_BUILD_AS_DLL /DLUA_LIB /I..\lua rings.c ..\lua\lua51.lib
+%COMPILE% /LD /DLUA_BUILD_AS_DLL /DLUA_LIB /I..\lua pluto.c ..\lua\lua51.lib
+xcopy /Y rings.dll %MLUALIB_TARGET%
+xcopy /Y bit.dll   %MLUALIB_TARGET%
+xcopy /Y pluto.dll %MLUALIB_TARGET%
+cd ..
+
+:w32stub
+echo @set LUA_ROOT=%MLUALIB_TARGET%> %MLUALIB_TARGET%\metalua.bat
+type win32\metalua.bat >> %MLUALIB_TARGET%\metalua.bat
+
+:setenv
+@REM set Metalua environment
+echo set LUA_ROOT=%MLUALIB_TARGET%> mlua_setenv.bat
+echo set LUA_PATH=?.luac;?.lua;%MLUALIB_TARGET%\?.luac;%MLUALIB_TARGET%\?.lua>> mlua_setenv.bat
+echo set LUA_CPATH=?.dll;%MLUALIB_TARGET%\?.dll;%MLUALIB_TARGET%\?\linit.dll>> mlua_setenv.bat
+echo set LUA_MPATH=?.mlua;%MLUALIB_TARGET%\?.mlua>> mlua_setenv.bat
+echo set PATH=%MLUALIB_TARGET%;%PATH%>> mlua_setenv.bat
+CALL mlua_setenv.bat
+
+:compiler
+@REM Build the compiler *.lua libs
+cd compiler
+set LUA=..\lua\lua.exe
+set LUAC=..\lua\luac.exe
+%LUAC% -o bytecode.luac lopcodes.lua lcode.lua ldump.lua compile.lua
+%LUAC% -o mlp.luac lexer.lua gg.lua mlp_lexer.lua mlp_misc.lua mlp_table.lua mlp_meta.lua mlp_expr.lua mlp_stat.lua mlp_ext.lua
+xcopy /Y bytecode.luac %MLUALIB_TARGET%
+xcopy /Y mlp.luac %MLUALIB_TARGET%
+
+@REM Build the compiler *.mlua parts
+%LUA% bootstrap.lua mlc.mlua
+%LUA% bootstrap.lua metalua.mlua
+copy /Y mlc.luac %MLUALIB_TARGET%
+copy /Y metalua.luac %MLUALIB_TARGET%
+cd ..
+
+:compile_srclib
+@REM Precompile the .mlua files in the library
 lua\lua win32\precompile.lua %MLUALIB_TARGET%
\ No newline at end of file