← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/update_eris into lp:widelands

 

SirVer has proposed merging lp:~widelands-dev/widelands/update_eris into lp:widelands.

Commit message:
Update Eris to 683ac97476a8634d9e5c17f0dec8dff8b7f3e595.


Eris has been recently updated to a released version - however that version is already 1 year old. Since then, master has received one bug fix and an update to the Lua version used. It also fixes a really annoying compile warning in Widelands. So I think it is worthwhile to update it again. 

I think this should not affect savegame compatibility. 


Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/update_eris/+merge/292700
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/update_eris into lp:widelands.
=== modified file 'src/third_party/eris/README.eris'
--- src/third_party/eris/README.eris	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/README.eris	2016-04-23 09:01:53 +0000
@@ -1,10 +1,11 @@
 This directory contains a verbatim copy of Eris by Florian Nücke.
 
 URL: https://github.com/fnuecke/eris
-VERSION: 1.1.0 for Lua 5.3
+VERSION: 683ac97476a8634d9e5c17f0dec8dff8b7f3e595 (Lua 5.3)
+SNAPSHOT: https://github.com/fnuecke/eris/commits/683ac97476a8634d9e5c17f0dec8dff8b7f3e595
 
 We use this for heavy persistence and it also brings with it the Lua version
-that we use in Widelands. The Widelands Team wishes to expresses total and
+that we use in Widelands. The Widelands team wishes to expresses total and
 complete gratitude to the authors of Eris for making it available under the MIT
 License.
 

=== modified file 'src/third_party/eris/eris.c'
--- src/third_party/eris/eris.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/eris.c	2016-04-23 09:01:53 +0000
@@ -37,6 +37,7 @@
 #define LUA_CORE
 
 /* Public Lua headers. */
+#include "lapi.h"
 #include "lua.h"
 #include "lauxlib.h"
 #include "lualib.h"
@@ -104,9 +105,8 @@
  * patched Lua version to be able to persist some of the library functions,
  * anyway: it needs to put the continuation C functions in the perms table. */
 /* ldebug.h */
-#define eris_ci_func ci_func
+#define eris_ci_func(ci)		(clLvalue((ci)->func))
 /* ldo.h */
-#define eris_incr_top incr_top
 #define eris_savestack savestack
 #define eris_restorestack restorestack
 #define eris_reallocstack luaD_reallocstack
@@ -342,7 +342,7 @@
 pushtstring(lua_State* L, TString *ts) {                               /* ... */
   if (ts) {
     eris_setsvalue2n(L, L->top, ts);
-    eris_incr_top(L);                                              /* ... str */
+    api_incr_top(L);                                              /* ... str */
   }
   else {
     lua_pushnil(L);                                                /* ... nil */
@@ -1573,7 +1573,7 @@
     /* Create closure and anchor it on the stack (avoid collection via GC). */
     cl = eris_newLclosure(info->L, nups);
     eris_setclLvalue(info->L, info->L->top, cl);                   /* ... lcl */
-    eris_incr_top(info->L);
+    api_incr_top(info->L);
 
     /* Preregister closure for handling of cycles (upvalues). */
     registerobject(info);

=== modified file 'src/third_party/eris/lapi.c'
--- src/third_party/eris/lapi.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lapi.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 2.244 2014/12/26 14:43:45 roberto Exp $
+** $Id: lapi.c,v 2.257 2015/11/02 18:48:07 roberto Exp $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -51,29 +51,29 @@
 /* test for valid but not pseudo index */
 #define isstackindex(i, o)	(isvalid(o) && !ispseudo(i))
 
-#define api_checkvalidindex(o)  api_check(isvalid(o), "invalid index")
+#define api_checkvalidindex(l,o)  api_check(l, isvalid(o), "invalid index")
 
-#define api_checkstackindex(i, o)  \
-	api_check(isstackindex(i, o), "index not in the stack")
+#define api_checkstackindex(l, i, o)  \
+	api_check(l, isstackindex(i, o), "index not in the stack")
 
 
 static TValue *index2addr (lua_State *L, int idx) {
   CallInfo *ci = L->ci;
   if (idx > 0) {
     TValue *o = ci->func + idx;
-    api_check(idx <= ci->top - (ci->func + 1), "unacceptable index");
+    api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index");
     if (o >= L->top) return NONVALIDVALUE;
     else return o;
   }
   else if (!ispseudo(idx)) {  /* negative index */
-    api_check(idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index");
+    api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index");
     return L->top + idx;
   }
   else if (idx == LUA_REGISTRYINDEX)
     return &G(L)->l_registry;
   else {  /* upvalues */
     idx = LUA_REGISTRYINDEX - idx;
-    api_check(idx <= MAXUPVAL + 1, "upvalue index too large");
+    api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large");
     if (ttislcf(ci->func))  /* light C function? */
       return NONVALIDVALUE;  /* it has no upvalues */
     else {
@@ -98,7 +98,7 @@
   int res;
   CallInfo *ci = L->ci;
   lua_lock(L);
-  api_check(n >= 0, "negative 'n'");
+  api_check(L, n >= 0, "negative 'n'");
   if (L->stack_last - L->top > n)  /* stack large enough? */
     res = 1;  /* yes; check is OK */
   else {  /* no; need to grow stack */
@@ -120,11 +120,12 @@
   if (from == to) return;
   lua_lock(to);
   api_checknelems(from, n);
-  api_check(G(from) == G(to), "moving among independent states");
-  api_check(to->ci->top - to->top >= n, "not enough elements to move");
+  api_check(from, G(from) == G(to), "moving among independent states");
+  api_check(from, to->ci->top - to->top >= n, "stack overflow");
   from->top -= n;
   for (i = 0; i < n; i++) {
-    setobj2s(to, to->top++, from->top + i);
+    setobj2s(to, to->top, from->top + i);
+    to->top++;  /* stack already checked by previous 'api_check' */
   }
   lua_unlock(to);
 }
@@ -159,7 +160,7 @@
 LUA_API int lua_absindex (lua_State *L, int idx) {
   return (idx > 0 || ispseudo(idx))
          ? idx
-         : cast_int(L->top - L->ci->func + idx);
+         : cast_int(L->top - L->ci->func) + idx;
 }
 
 
@@ -172,13 +173,13 @@
   StkId func = L->ci->func;
   lua_lock(L);
   if (idx >= 0) {
-    api_check(idx <= L->stack_last - (func + 1), "new top too large");
+    api_check(L, idx <= L->stack_last - (func + 1), "new top too large");
     while (L->top < (func + 1) + idx)
       setnilvalue(L->top++);
     L->top = (func + 1) + idx;
   }
   else {
-    api_check(-(idx+1) <= (L->top - (func + 1)), "invalid new top");
+    api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top");
     L->top += idx+1;  /* 'subtract' index (index is negative) */
   }
   lua_unlock(L);
@@ -208,8 +209,8 @@
   lua_lock(L);
   t = L->top - 1;  /* end of stack segment being rotated */
   p = index2addr(L, idx);  /* start of segment */
-  api_checkstackindex(idx, p);
-  api_check((n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'");
+  api_checkstackindex(L, idx, p);
+  api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'");
   m = (n >= 0 ? t - n : p - n - 1);  /* end of prefix */
   reverse(L, p, m);  /* reverse the prefix with length 'n' */
   reverse(L, m + 1, t);  /* reverse the suffix */
@@ -223,7 +224,7 @@
   lua_lock(L);
   fr = index2addr(L, fromidx);
   to = index2addr(L, toidx);
-  api_checkvalidindex(to);
+  api_checkvalidindex(L, to);
   setobj(L, to, fr);
   if (isupvalue(toidx))  /* function upvalue? */
     luaC_barrier(L, clCvalue(L->ci->func), fr);
@@ -255,7 +256,7 @@
 
 LUA_API const char *lua_typename (lua_State *L, int t) {
   UNUSED(L);
-  api_check(LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag");
+  api_check(L, LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag");
   return ttypename(t);
 }
 
@@ -305,7 +306,7 @@
   else {  /* for unary operations, add fake 2nd operand */
     api_checknelems(L, 1);
     setobjs2s(L, L->top, L->top - 1);
-    L->top++;
+    api_incr_top(L);
   }
   /* first operand at top - 2, second at top - 1; result go to top - 2 */
   luaO_arith(L, op, L->top - 2, L->top - 1, L->top - 2);
@@ -325,7 +326,7 @@
       case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break;
       case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break;
       case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break;
-      default: api_check(0, "invalid option");
+      default: api_check(L, 0, "invalid option");
     }
   }
   lua_unlock(L);
@@ -382,15 +383,17 @@
     luaO_tostring(L, o);
     lua_unlock(L);
   }
-  if (len != NULL) *len = tsvalue(o)->len;
+  if (len != NULL)
+    *len = vslen(o);
   return svalue(o);
 }
 
 
 LUA_API size_t lua_rawlen (lua_State *L, int idx) {
   StkId o = index2addr(L, idx);
-  switch (ttnov(o)) {
-    case LUA_TSTRING: return tsvalue(o)->len;
+  switch (ttype(o)) {
+    case LUA_TSHRSTR: return tsvalue(o)->shrlen;
+    case LUA_TLNGSTR: return tsvalue(o)->u.lnglen;
     case LUA_TUSERDATA: return uvalue(o)->len;
     case LUA_TTABLE: return luaH_getn(hvalue(o));
     default: return 0;
@@ -431,9 +434,8 @@
     case LUA_TCCL: return clCvalue(o);
     case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o)));
     case LUA_TTHREAD: return thvalue(o);
-    case LUA_TUSERDATA:
-    case LUA_TLIGHTUSERDATA:
-      return lua_touserdata(L, idx);
+    case LUA_TUSERDATA: return getudatamem(uvalue(o));
+    case LUA_TLIGHTUSERDATA: return pvalue(o);
     default: return NULL;
   }
 }
@@ -469,11 +471,16 @@
 }
 
 
+/*
+** Pushes on the stack a string with given length. Avoid using 's' when
+** 'len' == 0 (as 's' can be NULL in that case), due to later use of
+** 'memcmp' and 'memcpy'.
+*/
 LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) {
   TString *ts;
   lua_lock(L);
   luaC_checkGC(L);
-  ts = luaS_newlstr(L, s, len);
+  ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len);
   setsvalue2s(L, L->top, ts);
   api_incr_top(L);
   lua_unlock(L);
@@ -482,20 +489,19 @@
 
 
 LUA_API const char *lua_pushstring (lua_State *L, const char *s) {
-  if (s == NULL) {
-    lua_pushnil(L);
-    return NULL;
-  }
+  lua_lock(L);
+  if (s == NULL)
+    setnilvalue(L->top);
   else {
     TString *ts;
-    lua_lock(L);
     luaC_checkGC(L);
     ts = luaS_new(L, s);
     setsvalue2s(L, L->top, ts);
-    api_incr_top(L);
-    lua_unlock(L);
-    return getstr(ts);
+    s = getstr(ts);  /* internal copy's address */
   }
+  api_incr_top(L);
+  lua_unlock(L);
+  return s;
 }
 
 
@@ -531,7 +537,7 @@
   else {
     CClosure *cl;
     api_checknelems(L, n);
-    api_check(n <= MAXUPVAL, "upvalue index too large");
+    api_check(L, n <= MAXUPVAL, "upvalue index too large");
     luaC_checkGC(L);
     cl = luaF_newCclosure(L, n);
     cl->f = fn;
@@ -578,15 +584,27 @@
 */
 
 
+static int auxgetstr (lua_State *L, const TValue *t, const char *k) {
+  const TValue *aux;
+  TString *str = luaS_new(L, k);
+  if (luaV_fastget(L, t, str, aux, luaH_getstr)) {
+    setobj2s(L, L->top, aux);
+    api_incr_top(L);
+  }
+  else {
+    setsvalue2s(L, L->top, str);
+    api_incr_top(L);
+    luaV_finishget(L, t, L->top - 1, L->top - 1, aux);
+  }
+  lua_unlock(L);
+  return ttnov(L->top - 1);
+}
+
+
 LUA_API int lua_getglobal (lua_State *L, const char *name) {
   Table *reg = hvalue(&G(L)->l_registry);
-  const TValue *gt;  /* global table */
   lua_lock(L);
-  gt = luaH_getint(reg, LUA_RIDX_GLOBALS);
-  setsvalue2s(L, L->top++, luaS_new(L, name));
-  luaV_gettable(L, gt, L->top - 1, L->top - 1);
-  lua_unlock(L);
-  return ttnov(L->top - 1);
+  return auxgetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name);
 }
 
 
@@ -601,24 +619,25 @@
 
 
 LUA_API int lua_getfield (lua_State *L, int idx, const char *k) {
-  StkId t;
   lua_lock(L);
-  t = index2addr(L, idx);
-  setsvalue2s(L, L->top, luaS_new(L, k));
-  api_incr_top(L);
-  luaV_gettable(L, t, L->top - 1, L->top - 1);
-  lua_unlock(L);
-  return ttnov(L->top - 1);
+  return auxgetstr(L, index2addr(L, idx), k);
 }
 
 
 LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) {
   StkId t;
+  const TValue *aux;
   lua_lock(L);
   t = index2addr(L, idx);
-  setivalue(L->top, n);
-  api_incr_top(L);
-  luaV_gettable(L, t, L->top - 1, L->top - 1);
+  if (luaV_fastget(L, t, n, aux, luaH_getint)) {
+    setobj2s(L, L->top, aux);
+    api_incr_top(L);
+  }
+  else {
+    setivalue(L->top, n);
+    api_incr_top(L);
+    luaV_finishget(L, t, L->top - 1, L->top - 1, aux);
+  }
   lua_unlock(L);
   return ttnov(L->top - 1);
 }
@@ -628,7 +647,7 @@
   StkId t;
   lua_lock(L);
   t = index2addr(L, idx);
-  api_check(ttistable(t), "table expected");
+  api_check(L, ttistable(t), "table expected");
   setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));
   lua_unlock(L);
   return ttnov(L->top - 1);
@@ -639,7 +658,7 @@
   StkId t;
   lua_lock(L);
   t = index2addr(L, idx);
-  api_check(ttistable(t), "table expected");
+  api_check(L, ttistable(t), "table expected");
   setobj2s(L, L->top, luaH_getint(hvalue(t), n));
   api_incr_top(L);
   lua_unlock(L);
@@ -652,7 +671,7 @@
   TValue k;
   lua_lock(L);
   t = index2addr(L, idx);
-  api_check(ttistable(t), "table expected");
+  api_check(L, ttistable(t), "table expected");
   setpvalue(&k, cast(void *, p));
   setobj2s(L, L->top, luaH_get(hvalue(t), &k));
   api_incr_top(L);
@@ -705,7 +724,7 @@
   StkId o;
   lua_lock(L);
   o = index2addr(L, idx);
-  api_check(ttisfulluserdata(o), "full userdata expected");
+  api_check(L, ttisfulluserdata(o), "full userdata expected");
   getuservalue(L, uvalue(o), L->top);
   api_incr_top(L);
   lua_unlock(L);
@@ -717,17 +736,29 @@
 ** set functions (stack -> Lua)
 */
 
+/*
+** t[k] = value at the top of the stack (where 'k' is a string)
+*/
+static void auxsetstr (lua_State *L, const TValue *t, const char *k) {
+  const TValue *aux;
+  TString *str = luaS_new(L, k);
+  api_checknelems(L, 1);
+  if (luaV_fastset(L, t, str, aux, luaH_getstr, L->top - 1))
+    L->top--;  /* pop value */
+  else {
+    setsvalue2s(L, L->top, str);  /* push 'str' (to make it a TValue) */
+    api_incr_top(L);
+    luaV_finishset(L, t, L->top - 1, L->top - 2, aux);
+    L->top -= 2;  /* pop value and key */
+  }
+  lua_unlock(L);  /* lock done by caller */
+}
+
 
 LUA_API void lua_setglobal (lua_State *L, const char *name) {
   Table *reg = hvalue(&G(L)->l_registry);
-  const TValue *gt;  /* global table */
-  lua_lock(L);
-  api_checknelems(L, 1);
-  gt = luaH_getint(reg, LUA_RIDX_GLOBALS);
-  setsvalue2s(L, L->top++, luaS_new(L, name));
-  luaV_settable(L, gt, L->top - 1, L->top - 2);
-  L->top -= 2;  /* pop value and key */
-  lua_unlock(L);
+  lua_lock(L);  /* unlock done in 'auxsetstr' */
+  auxsetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name);
 }
 
 
@@ -743,40 +774,40 @@
 
 
 LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
-  StkId t;
-  lua_lock(L);
-  api_checknelems(L, 1);
-  t = index2addr(L, idx);
-  setsvalue2s(L, L->top++, luaS_new(L, k));
-  luaV_settable(L, t, L->top - 1, L->top - 2);
-  L->top -= 2;  /* pop value and key */
-  lua_unlock(L);
+  lua_lock(L);  /* unlock done in 'auxsetstr' */
+  auxsetstr(L, index2addr(L, idx), k);
 }
 
 
 LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) {
   StkId t;
+  const TValue *aux;
   lua_lock(L);
   api_checknelems(L, 1);
   t = index2addr(L, idx);
-  setivalue(L->top++, n);
-  luaV_settable(L, t, L->top - 1, L->top - 2);
-  L->top -= 2;  /* pop value and key */
+  if (luaV_fastset(L, t, n, aux, luaH_getint, L->top - 1))
+    L->top--;  /* pop value */
+  else {
+    setivalue(L->top, n);
+    api_incr_top(L);
+    luaV_finishset(L, t, L->top - 1, L->top - 2, aux);
+    L->top -= 2;  /* pop value and key */
+  }
   lua_unlock(L);
 }
 
 
 LUA_API void lua_rawset (lua_State *L, int idx) {
   StkId o;
-  Table *t;
+  TValue *slot;
   lua_lock(L);
   api_checknelems(L, 2);
   o = index2addr(L, idx);
-  api_check(ttistable(o), "table expected");
-  t = hvalue(o);
-  setobj2t(L, luaH_set(L, t, L->top-2), L->top-1);
-  invalidateTMcache(t);
-  luaC_barrierback(L, t, L->top-1);
+  api_check(L, ttistable(o), "table expected");
+  slot = luaH_set(L, hvalue(o), L->top - 2);
+  setobj2t(L, slot, L->top - 1);
+  invalidateTMcache(hvalue(o));
+  luaC_barrierback(L, hvalue(o), L->top-1);
   L->top -= 2;
   lua_unlock(L);
 }
@@ -784,14 +815,12 @@
 
 LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) {
   StkId o;
-  Table *t;
   lua_lock(L);
   api_checknelems(L, 1);
   o = index2addr(L, idx);
-  api_check(ttistable(o), "table expected");
-  t = hvalue(o);
-  luaH_setint(L, t, n, L->top - 1);
-  luaC_barrierback(L, t, L->top-1);
+  api_check(L, ttistable(o), "table expected");
+  luaH_setint(L, hvalue(o), n, L->top - 1);
+  luaC_barrierback(L, hvalue(o), L->top-1);
   L->top--;
   lua_unlock(L);
 }
@@ -799,16 +828,15 @@
 
 LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) {
   StkId o;
-  Table *t;
-  TValue k;
+  TValue k, *slot;
   lua_lock(L);
   api_checknelems(L, 1);
   o = index2addr(L, idx);
-  api_check(ttistable(o), "table expected");
-  t = hvalue(o);
+  api_check(L, ttistable(o), "table expected");
   setpvalue(&k, cast(void *, p));
-  setobj2t(L, luaH_set(L, t, &k), L->top - 1);
-  luaC_barrierback(L, t, L->top - 1);
+  slot = luaH_set(L, hvalue(o), &k);
+  setobj2t(L, slot, L->top - 1);
+  luaC_barrierback(L, hvalue(o), L->top - 1);
   L->top--;
   lua_unlock(L);
 }
@@ -823,7 +851,7 @@
   if (ttisnil(L->top - 1))
     mt = NULL;
   else {
-    api_check(ttistable(L->top - 1), "table expected");
+    api_check(L, ttistable(L->top - 1), "table expected");
     mt = hvalue(L->top - 1);
   }
   switch (ttnov(obj)) {
@@ -859,7 +887,7 @@
   lua_lock(L);
   api_checknelems(L, 1);
   o = index2addr(L, idx);
-  api_check(ttisfulluserdata(o), "full userdata expected");
+  api_check(L, ttisfulluserdata(o), "full userdata expected");
   setuservalue(L, uvalue(o), L->top - 1);
   luaC_barrier(L, gcvalue(o), L->top - 1);
   L->top--;
@@ -873,7 +901,7 @@
 
 
 #define checkresults(L,na,nr) \
-     api_check((nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \
+     api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \
 	"results from function overflow current stack size")
 
 
@@ -881,19 +909,19 @@
                         lua_KContext ctx, lua_KFunction k) {
   StkId func;
   lua_lock(L);
-  api_check(k == NULL || !isLua(L->ci),
+  api_check(L, k == NULL || !isLua(L->ci),
     "cannot use continuations inside hooks");
   api_checknelems(L, nargs+1);
-  api_check(L->status == LUA_OK, "cannot do calls on non-normal thread");
+  api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread");
   checkresults(L, nargs, nresults);
   func = L->top - (nargs+1);
   if (k != NULL && L->nny == 0) {  /* need to prepare continuation? */
     L->ci->u.c.k = k;  /* save continuation */
     L->ci->u.c.ctx = ctx;  /* save context */
-    luaD_call(L, func, nresults, 1);  /* do the call */
+    luaD_call(L, func, nresults);  /* do the call */
   }
   else  /* no continuation or no yieldable */
-    luaD_call(L, func, nresults, 0);  /* just do the call */
+    luaD_callnoyield(L, func, nresults);  /* just do the call */
   adjustresults(L, nresults);
   lua_unlock(L);
 }
@@ -911,7 +939,7 @@
 
 static void f_call (lua_State *L, void *ud) {
   struct CallS *c = cast(struct CallS *, ud);
-  luaD_call(L, c->func, c->nresults, 0);
+  luaD_callnoyield(L, c->func, c->nresults);
 }
 
 
@@ -922,16 +950,16 @@
   int status;
   ptrdiff_t func;
   lua_lock(L);
-  api_check(k == NULL || !isLua(L->ci),
+  api_check(L, k == NULL || !isLua(L->ci),
     "cannot use continuations inside hooks");
   api_checknelems(L, nargs+1);
-  api_check(L->status == LUA_OK, "cannot do calls on non-normal thread");
+  api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread");
   checkresults(L, nargs, nresults);
   if (errfunc == 0)
     func = 0;
   else {
     StkId o = index2addr(L, errfunc);
-    api_checkstackindex(errfunc, o);
+    api_checkstackindex(L, errfunc, o);
     func = savestack(L, o);
   }
   c.func = L->top - (nargs+1);  /* function to be called */
@@ -949,7 +977,7 @@
     L->errfunc = func;
     setoah(ci->callstatus, L->allowhook);  /* save value of 'allowhook' */
     ci->callstatus |= CIST_YPCALL;  /* function can do error recovery */
-    luaD_call(L, c.func, nresults, 1);  /* do the call */
+    luaD_call(L, c.func, nresults);  /* do the call */
     ci->callstatus &= ~CIST_YPCALL;
     L->errfunc = ci->u.c.old_errfunc;
     status = LUA_OK;  /* if it is here, there were no errors */
@@ -1038,7 +1066,7 @@
     }
     case LUA_GCSTEP: {
       l_mem debt = 1;  /* =1 to signal that it did an actual step */
-      int oldrunning = g->gcrunning;
+      lu_byte oldrunning = g->gcrunning;
       g->gcrunning = 1;  /* allow GC to run */
       if (data == 0) {
         luaE_setdebt(g, -GCSTEPSIZE);  /* to do a "small" step */
@@ -1096,7 +1124,7 @@
   int more;
   lua_lock(L);
   t = index2addr(L, idx);
-  api_check(ttistable(t), "table expected");
+  api_check(L, ttistable(t), "table expected");
   more = luaH_next(L, hvalue(t), L->top - 1);
   if (more) {
     api_incr_top(L);
@@ -1228,9 +1256,9 @@
 static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) {
   LClosure *f;
   StkId fi = index2addr(L, fidx);
-  api_check(ttisLclosure(fi), "Lua function expected");
+  api_check(L, ttisLclosure(fi), "Lua function expected");
   f = clLvalue(fi);
-  api_check((1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index");
+  api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index");
   if (pf) *pf = f;
   return &f->upvals[n - 1];  /* get its upvalue pointer */
 }
@@ -1244,11 +1272,11 @@
     }
     case LUA_TCCL: {  /* C closure */
       CClosure *f = clCvalue(fi);
-      api_check(1 <= n && n <= f->nupvalues, "invalid upvalue index");
+      api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index");
       return &f->upvalue[n - 1];
     }
     default: {
-      api_check(0, "closure expected");
+      api_check(L, 0, "closure expected");
       return NULL;
     }
   }

=== modified file 'src/third_party/eris/lapi.h'
--- src/third_party/eris/lapi.h	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lapi.h	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.h,v 2.8 2014/07/15 21:26:50 roberto Exp $
+** $Id: lapi.h,v 2.9 2015/03/06 19:49:50 roberto Exp $
 ** Auxiliary functions from Lua API
 ** See Copyright Notice in lua.h
 */
@@ -11,13 +11,13 @@
 #include "llimits.h"
 #include "lstate.h"
 
-#define api_incr_top(L)   {L->top++; api_check(L->top <= L->ci->top, \
+#define api_incr_top(L)   {L->top++; api_check(L, L->top <= L->ci->top, \
 				"stack overflow");}
 
 #define adjustresults(L,nres) \
     { if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; }
 
-#define api_checknelems(L,n)	api_check((n) < (L->top - L->ci->func), \
+#define api_checknelems(L,n)	api_check(L, (n) < (L->top - L->ci->func), \
 				  "not enough elements in the stack")
 
 

=== modified file 'src/third_party/eris/lauxlib.c'
--- src/third_party/eris/lauxlib.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lauxlib.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lauxlib.c,v 1.279 2014/12/14 18:32:26 roberto Exp $
+** $Id: lauxlib.c,v 1.284 2015/11/19 19:16:22 roberto Exp $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */
@@ -33,8 +33,8 @@
 */
 
 
-#define LEVELS1	12	/* size of the first part of the stack */
-#define LEVELS2	10	/* size of the second part of the stack */
+#define LEVELS1	10	/* size of the first part of the stack */
+#define LEVELS2	11	/* size of the second part of the stack */
 
 
 
@@ -107,7 +107,7 @@
 }
 
 
-static int countlevels (lua_State *L) {
+static int lastlevel (lua_State *L) {
   lua_Debug ar;
   int li = 1, le = 1;
   /* find an upper bound */
@@ -126,14 +126,16 @@
                                 const char *msg, int level) {
   lua_Debug ar;
   int top = lua_gettop(L);
-  int numlevels = countlevels(L1);
-  int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0;
-  if (msg) lua_pushfstring(L, "%s\n", msg);
+  int last = lastlevel(L1);
+  int n1 = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1;
+  if (msg)
+    lua_pushfstring(L, "%s\n", msg);
+  luaL_checkstack(L, 10, NULL);
   lua_pushliteral(L, "stack traceback:");
   while (lua_getstack(L1, level++, &ar)) {
-    if (level == mark) {  /* too many levels? */
+    if (n1-- == 0) {  /* too many levels? */
       lua_pushliteral(L, "\n\t...");  /* add a '...' */
-      level = numlevels - LEVELS2;  /* and skip to last ones */
+      level = last - LEVELS2 + 1;  /* and skip to last ones */
     }
     else {
       lua_getinfo(L1, "Slnt", &ar);
@@ -286,10 +288,10 @@
 */
 
 LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
-  if (luaL_getmetatable(L, tname))  /* name already in use? */
+  if (luaL_getmetatable(L, tname) != LUA_TNIL)  /* name already in use? */
     return 0;  /* leave previous value on top, but return 0 */
   lua_pop(L, 1);
-  lua_newtable(L);  /* create metatable */
+  lua_createtable(L, 0, 2);  /* create metatable */
   lua_pushstring(L, tname);
   lua_setfield(L, -2, "__name");  /* metatable.__name = tname */
   lua_pushvalue(L, -1);
@@ -435,6 +437,47 @@
 ** =======================================================
 */
 
+/* userdata to box arbitrary data */
+typedef struct UBox {
+  void *box;
+  size_t bsize;
+} UBox;
+
+
+static void *resizebox (lua_State *L, int idx, size_t newsize) {
+  void *ud;
+  lua_Alloc allocf = lua_getallocf(L, &ud);
+  UBox *box = (UBox *)lua_touserdata(L, idx);
+  void *temp = allocf(ud, box->box, box->bsize, newsize);
+  if (temp == NULL && newsize > 0) {  /* allocation error? */
+    resizebox(L, idx, 0);  /* free buffer */
+    luaL_error(L, "not enough memory for buffer allocation");
+  }
+  box->box = temp;
+  box->bsize = newsize;
+  return temp;
+}
+
+
+static int boxgc (lua_State *L) {
+  resizebox(L, 1, 0);
+  return 0;
+}
+
+
+static void *newbox (lua_State *L, size_t newsize) {
+  UBox *box = (UBox *)lua_newuserdata(L, sizeof(UBox));
+  box->box = NULL;
+  box->bsize = 0;
+  if (luaL_newmetatable(L, "LUABOX")) {  /* creating metatable? */
+    lua_pushcfunction(L, boxgc);
+    lua_setfield(L, -2, "__gc");  /* metatable.__gc = boxgc */
+  }
+  lua_setmetatable(L, -2);
+  return resizebox(L, -1, newsize);
+}
+
+
 /*
 ** check whether buffer is using a userdata on the stack as a temporary
 ** buffer
@@ -455,11 +498,12 @@
     if (newsize < B->n || newsize - B->n < sz)
       luaL_error(L, "buffer too large");
     /* create larger buffer */
-    newbuff = (char *)lua_newuserdata(L, newsize * sizeof(char));
-    /* move content to new buffer */
-    memcpy(newbuff, B->b, B->n * sizeof(char));
     if (buffonstack(B))
-      lua_remove(L, -2);  /* remove old buffer */
+      newbuff = (char *)resizebox(L, -1, newsize);
+    else {  /* no buffer yet */
+      newbuff = (char *)newbox(L, newsize);
+      memcpy(newbuff, B->b, B->n * sizeof(char));  /* copy original content */
+    }
     B->b = newbuff;
     B->size = newsize;
   }
@@ -468,9 +512,11 @@
 
 
 LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {
-  char *b = luaL_prepbuffsize(B, l);
-  memcpy(b, s, l * sizeof(char));
-  luaL_addsize(B, l);
+  if (l > 0) {  /* avoid 'memcpy' when 's' can be NULL */
+    char *b = luaL_prepbuffsize(B, l);
+    memcpy(b, s, l * sizeof(char));
+    luaL_addsize(B, l);
+  }
 }
 
 
@@ -482,8 +528,10 @@
 LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
   lua_State *L = B->L;
   lua_pushlstring(L, B->b, B->n);
-  if (buffonstack(B))
-    lua_remove(L, -2);  /* remove old buffer */
+  if (buffonstack(B)) {
+    resizebox(L, -2, 0);  /* delete old buffer */
+    lua_remove(L, -2);  /* remove its header from the stack */
+  }
 }
 
 
@@ -605,7 +653,7 @@
 
 
 static int skipBOM (LoadF *lf) {
-  const char *p = "\xEF\xBB\xBF";  /* Utf8 BOM mark */
+  const char *p = "\xEF\xBB\xBF";  /* UTF-8 BOM mark */
   int c;
   lf->n = 0;
   do {

=== modified file 'src/third_party/eris/lauxlib.h'
--- src/third_party/eris/lauxlib.h	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lauxlib.h	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lauxlib.h,v 1.128 2014/10/29 16:11:17 roberto Exp $
+** $Id: lauxlib.h,v 1.129 2015/11/23 11:29:43 roberto Exp $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */
@@ -65,7 +65,7 @@
 LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname);
 LUALIB_API int (luaL_execresult) (lua_State *L, int stat);
 
-/* pre-defined references */
+/* predefined references */
 #define LUA_NOREF       (-2)
 #define LUA_REFNIL      (-1)
 

=== modified file 'src/third_party/eris/lbaselib.c'
--- src/third_party/eris/lbaselib.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lbaselib.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lbaselib.c,v 1.309 2014/12/10 12:26:42 roberto Exp $
+** $Id: lbaselib.c,v 1.312 2015/10/29 15:21:04 roberto Exp $
 ** Basic library
 ** See Copyright Notice in lua.h
 */
@@ -55,7 +55,7 @@
     return NULL;
   do {
     int digit = (isdigit((unsigned char)*s)) ? *s - '0'
-                   : toupper((unsigned char)*s) - 'A' + 10;
+                   : (toupper((unsigned char)*s) - 'A') + 10;
     if (digit >= base) return NULL;  /* invalid numeral */
     n = n * base + digit;
     s++;
@@ -86,8 +86,8 @@
     const char *s;
     lua_Integer n = 0;  /* to avoid warnings */
     lua_Integer base = luaL_checkinteger(L, 2);
-    luaL_checktype(L, 1, LUA_TSTRING);  /* before 'luaL_checklstring'! */
-    s = luaL_checklstring(L, 1, &l);
+    luaL_checktype(L, 1, LUA_TSTRING);  /* no numbers as strings */
+    s = lua_tolstring(L, 1, &l);
     luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
     if (b_str2int(s, (int)base, &n) == s + l) {
       lua_pushinteger(L, n);
@@ -198,12 +198,10 @@
 }
 
 
-/*
-** This function has all type names as upvalues, to maximize performance.
-*/
 static int luaB_type (lua_State *L) {
-  luaL_checkany(L, 1);
-  lua_pushvalue(L, lua_upvalueindex(lua_type(L, 1) + 1));
+  int t = lua_type(L, 1);
+  luaL_argcheck(L, t != LUA_TNONE, 1, "value expected");
+  lua_pushstring(L, lua_typename(L, t));
   return 1;
 }
 
@@ -243,18 +241,7 @@
 
 
 /*
-** Traversal function for 'ipairs' for raw tables
-*/
-static int ipairsaux_raw (lua_State *L) {
-  lua_Integer i = luaL_checkinteger(L, 2) + 1;
-  luaL_checktype(L, 1, LUA_TTABLE);
-  lua_pushinteger(L, i);
-  return (lua_rawgeti(L, 1, i) == LUA_TNIL) ? 1 : 2;
-}
-
-
-/*
-** Traversal function for 'ipairs' for tables with metamethods
+** Traversal function for 'ipairs'
 */
 static int ipairsaux (lua_State *L) {
   lua_Integer i = luaL_checkinteger(L, 2) + 1;
@@ -269,13 +256,11 @@
 ** that can affect the traversal.
 */
 static int luaB_ipairs (lua_State *L) {
-  lua_CFunction iter = (luaL_getmetafield(L, 1, "__index") != LUA_TNIL)
-                       ? ipairsaux : ipairsaux_raw;
 #if defined(LUA_COMPAT_IPAIRS)
-  return pairsmeta(L, "__ipairs", 1, iter);
+  return pairsmeta(L, "__ipairs", 1, ipairsaux);
 #else
   luaL_checkany(L, 1);
-  lua_pushcfunction(L, iter);  /* iteration function */
+  lua_pushcfunction(L, ipairsaux);  /* iteration function */
   lua_pushvalue(L, 1);  /* state */
   lua_pushinteger(L, 0);  /* initial value */
   return 3;
@@ -490,9 +475,9 @@
   {"setmetatable", luaB_setmetatable},
   {"tonumber", luaB_tonumber},
   {"tostring", luaB_tostring},
+  {"type", luaB_type},
   {"xpcall", luaB_xpcall},
   /* placeholders */
-  {"type", NULL},
   {"_G", NULL},
   {"_VERSION", NULL},
   {NULL, NULL}
@@ -500,7 +485,6 @@
 
 
 LUAMOD_API int luaopen_base (lua_State *L) {
-  int i;
   /* open lib into global table */
   lua_pushglobaltable(L);
   luaL_setfuncs(L, base_funcs, 0);
@@ -510,11 +494,6 @@
   /* set global _VERSION */
   lua_pushliteral(L, LUA_VERSION);
   lua_setfield(L, -2, "_VERSION");
-  /* set function 'type' with proper upvalues */
-  for (i = 0; i < LUA_NUMTAGS; i++)  /* push all type names as upvalues */
-    lua_pushstring(L, lua_typename(L, i));
-  lua_pushcclosure(L, luaB_type, LUA_NUMTAGS);
-  lua_setfield(L, -2, "type");
   return 1;
 }
 
@@ -555,15 +534,5 @@
     lua_pushstring(L, "__eris.baselib_ipairsaux");
   }
   lua_rawset(L, -3);
-
-  if (forUnpersist) {
-    lua_pushstring(L, "__eris.baselib_ipairsaux_raw");
-    lua_pushcfunction(L, ipairsaux_raw);
-  }
-  else {
-    lua_pushcfunction(L, ipairsaux_raw);
-    lua_pushstring(L, "__eris.baselib_ipairsaux_raw");
-  }
-  lua_rawset(L, -3);
 }
 

=== modified file 'src/third_party/eris/lbitlib.c'
--- src/third_party/eris/lbitlib.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lbitlib.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lbitlib.c,v 1.28 2014/11/02 19:19:04 roberto Exp $
+** $Id: lbitlib.c,v 1.30 2015/11/11 19:08:09 roberto Exp $
 ** Standard library for bitwise operations
 ** See Copyright Notice in lua.h
 */
@@ -19,6 +19,10 @@
 #if defined(LUA_COMPAT_BITLIB)		/* { */
 
 
+#define pushunsigned(L,n)	lua_pushinteger(L, (lua_Integer)(n))
+#define checkunsigned(L,i)	((lua_Unsigned)luaL_checkinteger(L,i))
+
+
 /* number of bits to consider in a number */
 #if !defined(LUA_NBITS)
 #define LUA_NBITS	32
@@ -46,14 +50,14 @@
   int i, n = lua_gettop(L);
   lua_Unsigned r = ~(lua_Unsigned)0;
   for (i = 1; i <= n; i++)
-    r &= luaL_checkunsigned(L, i);
+    r &= checkunsigned(L, i);
   return trim(r);
 }
 
 
 static int b_and (lua_State *L) {
   lua_Unsigned r = andaux(L);
-  lua_pushunsigned(L, r);
+  pushunsigned(L, r);
   return 1;
 }
 
@@ -69,8 +73,8 @@
   int i, n = lua_gettop(L);
   lua_Unsigned r = 0;
   for (i = 1; i <= n; i++)
-    r |= luaL_checkunsigned(L, i);
-  lua_pushunsigned(L, trim(r));
+    r |= checkunsigned(L, i);
+  pushunsigned(L, trim(r));
   return 1;
 }
 
@@ -79,15 +83,15 @@
   int i, n = lua_gettop(L);
   lua_Unsigned r = 0;
   for (i = 1; i <= n; i++)
-    r ^= luaL_checkunsigned(L, i);
-  lua_pushunsigned(L, trim(r));
+    r ^= checkunsigned(L, i);
+  pushunsigned(L, trim(r));
   return 1;
 }
 
 
 static int b_not (lua_State *L) {
-  lua_Unsigned r = ~luaL_checkunsigned(L, 1);
-  lua_pushunsigned(L, trim(r));
+  lua_Unsigned r = ~checkunsigned(L, 1);
+  pushunsigned(L, trim(r));
   return 1;
 }
 
@@ -104,23 +108,23 @@
     else r <<= i;
     r = trim(r);
   }
-  lua_pushunsigned(L, r);
+  pushunsigned(L, r);
   return 1;
 }
 
 
 static int b_lshift (lua_State *L) {
-  return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkinteger(L, 2));
+  return b_shift(L, checkunsigned(L, 1), luaL_checkinteger(L, 2));
 }
 
 
 static int b_rshift (lua_State *L) {
-  return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkinteger(L, 2));
+  return b_shift(L, checkunsigned(L, 1), -luaL_checkinteger(L, 2));
 }
 
 
 static int b_arshift (lua_State *L) {
-  lua_Unsigned r = luaL_checkunsigned(L, 1);
+  lua_Unsigned r = checkunsigned(L, 1);
   lua_Integer i = luaL_checkinteger(L, 2);
   if (i < 0 || !(r & ((lua_Unsigned)1 << (LUA_NBITS - 1))))
     return b_shift(L, r, -i);
@@ -128,19 +132,19 @@
     if (i >= LUA_NBITS) r = ALLONES;
     else
       r = trim((r >> i) | ~(trim(~(lua_Unsigned)0) >> i));  /* add signal bit */
-    lua_pushunsigned(L, r);
+    pushunsigned(L, r);
     return 1;
   }
 }
 
 
 static int b_rot (lua_State *L, lua_Integer d) {
-  lua_Unsigned r = luaL_checkunsigned(L, 1);
+  lua_Unsigned r = checkunsigned(L, 1);
   int i = d & (LUA_NBITS - 1);  /* i = d % NBITS */
   r = trim(r);
   if (i != 0)  /* avoid undefined shift of LUA_NBITS when i == 0 */
     r = (r << i) | (r >> (LUA_NBITS - i));
-  lua_pushunsigned(L, trim(r));
+  pushunsigned(L, trim(r));
   return 1;
 }
 
@@ -175,23 +179,22 @@
 
 static int b_extract (lua_State *L) {
   int w;
-  lua_Unsigned r = trim(luaL_checkunsigned(L, 1));
+  lua_Unsigned r = trim(checkunsigned(L, 1));
   int f = fieldargs(L, 2, &w);
   r = (r >> f) & mask(w);
-  lua_pushunsigned(L, r);
+  pushunsigned(L, r);
   return 1;
 }
 
 
 static int b_replace (lua_State *L) {
   int w;
-  lua_Unsigned r = trim(luaL_checkunsigned(L, 1));
-  lua_Unsigned v = luaL_checkunsigned(L, 2);
+  lua_Unsigned r = trim(checkunsigned(L, 1));
+  lua_Unsigned v = trim(checkunsigned(L, 2));
   int f = fieldargs(L, 3, &w);
-  int m = mask(w);
-  v &= m;  /* erase bits outside given width */
-  r = (r & ~(m << f)) | (v << f);
-  lua_pushunsigned(L, r);
+  lua_Unsigned m = mask(w);
+  r = (r & ~(m << f)) | ((v & m) << f);
+  pushunsigned(L, r);
   return 1;
 }
 

=== modified file 'src/third_party/eris/lcode.c'
--- src/third_party/eris/lcode.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lcode.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 2.99 2014/12/29 16:49:25 roberto Exp $
+** $Id: lcode.c,v 2.103 2015/11/19 19:16:22 roberto Exp $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -29,15 +29,15 @@
 #include "lvm.h"
 
 
-/* Maximum number of registers in a Lua function */
-#define MAXREGS		250
+/* Maximum number of registers in a Lua function (must fit in 8 bits) */
+#define MAXREGS		255
 
 
 #define hasjumps(e)	((e)->t != (e)->f)
 
 
 static int tonumeral(expdesc *e, TValue *v) {
-  if (e->t != NO_JUMP || e->f != NO_JUMP)
+  if (hasjumps(e))
     return 0;  /* not a numeral */
   switch (e->k) {
     case VKINT:
@@ -279,7 +279,8 @@
   int newstack = fs->freereg + n;
   if (newstack > fs->f->maxstacksize) {
     if (newstack >= MAXREGS)
-      luaX_syntaxerror(fs->ls, "function or expression too complex");
+      luaX_syntaxerror(fs->ls,
+        "function or expression needs too many registers");
     fs->f->maxstacksize = cast_byte(newstack);
   }
 }
@@ -573,8 +574,8 @@
     case VKFLT: {
       e->u.info = luaK_numberK(fs, e->u.nval);
       e->k = VK;
-      /* go through */
     }
+    /* FALLTHROUGH */
     case VK: {
      vk:
       if (e->u.info <= MAXINDEXRK)  /* constant fits in 'argC'? */
@@ -793,7 +794,7 @@
 static void codeexpval (FuncState *fs, OpCode op,
                         expdesc *e1, expdesc *e2, int line) {
   lua_assert(op >= OP_ADD);
-  if (op <= OP_BNOT && constfolding(fs, op - OP_ADD + LUA_OPADD, e1, e2))
+  if (op <= OP_BNOT && constfolding(fs, (op - OP_ADD) + LUA_OPADD, e1, e2))
     return;  /* result has been folded */
   else {
     int o1, o2;
@@ -815,7 +816,7 @@
       freeexp(fs, e1);
     }
     e1->u.info = luaK_codeABC(fs, op, 0, o1, o2);  /* generate opcode */
-    e1->k = VRELOCABLE;  /* all those operations are relocable */
+    e1->k = VRELOCABLE;  /* all those operations are relocatable */
     luaK_fixline(fs, line);
   }
 }
@@ -920,11 +921,11 @@
       break;
     }
     case OPR_EQ: case OPR_LT: case OPR_LE: {
-      codecomp(fs, cast(OpCode, op - OPR_EQ + OP_EQ), 1, e1, e2);
+      codecomp(fs, cast(OpCode, (op - OPR_EQ) + OP_EQ), 1, e1, e2);
       break;
     }
     case OPR_NE: case OPR_GT: case OPR_GE: {
-      codecomp(fs, cast(OpCode, op - OPR_NE + OP_EQ), 0, e1, e2);
+      codecomp(fs, cast(OpCode, (op - OPR_NE) + OP_EQ), 0, e1, e2);
       break;
     }
     default: lua_assert(0);

=== modified file 'src/third_party/eris/ldblib.c'
--- src/third_party/eris/ldblib.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/ldblib.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: ldblib.c,v 1.148 2015/01/02 12:52:22 roberto Exp $
+** $Id: ldblib.c,v 1.151 2015/11/23 11:29:43 roberto Exp $
 ** Interface from Lua to its debug API
 ** See Copyright Notice in lua.h
 */
@@ -27,6 +27,17 @@
 static const int HOOKKEY = 0;
 
 
+/*
+** If L1 != L, L1 can be in any state, and therefore there are no
+** guarantees about its stack space; any push in L1 must be
+** checked.
+*/
+static void checkstack (lua_State *L, lua_State *L1, int n) {
+  if (L != L1 && !lua_checkstack(L1, n))
+    luaL_error(L, "stack overflow");
+}
+
+
 static int db_getregistry (lua_State *L) {
   lua_pushvalue(L, LUA_REGISTRYINDEX);
   return 1;
@@ -127,12 +138,16 @@
 
 /*
 ** Calls 'lua_getinfo' and collects all results in a new table.
+** L1 needs stack space for an optional input (function) plus
+** two optional outputs (function and line table) from function
+** 'lua_getinfo'.
 */
 static int db_getinfo (lua_State *L) {
   lua_Debug ar;
   int arg;
   lua_State *L1 = getthread(L, &arg);
   const char *options = luaL_optstring(L, arg+2, "flnStu");
+  checkstack(L, L1, 3);
   if (lua_isfunction(L, arg + 1)) {  /* info about a function? */
     options = lua_pushfstring(L, ">%s", options);  /* add '>' to 'options' */
     lua_pushvalue(L, arg + 1);  /* move function to 'L1' stack */
@@ -190,6 +205,7 @@
     int level = (int)luaL_checkinteger(L, arg + 1);
     if (!lua_getstack(L1, level, &ar))  /* out of range? */
       return luaL_argerror(L, arg+1, "level out of range");
+    checkstack(L, L1, 1);
     name = lua_getlocal(L1, &ar, nvar);
     if (name) {
       lua_xmove(L1, L, 1);  /* move local value */
@@ -216,6 +232,7 @@
     return luaL_argerror(L, arg+1, "level out of range");
   luaL_checkany(L, arg+3);
   lua_settop(L, arg+3);
+  checkstack(L, L1, 1);
   lua_xmove(L, L1, 1);
   name = lua_setlocal(L1, &ar, nvar);
   if (name == NULL)
@@ -350,6 +367,7 @@
     lua_pushvalue(L, -1);
     lua_setmetatable(L, -2);  /* setmetatable(hooktable) = hooktable */
   }
+  checkstack(L, L1, 1);
   lua_pushthread(L1); lua_xmove(L1, L, 1);  /* key (thread) */
   lua_pushvalue(L, arg + 1);  /* value (hook function) */
   lua_rawset(L, -3);  /* hooktable[L1] = new Lua hook */
@@ -370,6 +388,7 @@
     lua_pushliteral(L, "external hook");
   else {  /* hook table must exist */
     lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY);
+    checkstack(L, L1, 1);
     lua_pushthread(L1); lua_xmove(L1, L, 1);
     lua_rawget(L, -2);   /* 1st result = hooktable[L1] */
     lua_remove(L, -2);  /* remove hook table */

=== modified file 'src/third_party/eris/ldebug.c'
--- src/third_party/eris/ldebug.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/ldebug.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.c,v 2.110 2015/01/02 12:52:22 roberto Exp $
+** $Id: ldebug.c,v 2.117 2015/11/02 18:48:07 roberto Exp $
 ** Debug Interface
 ** See Copyright Notice in lua.h
 */
@@ -34,6 +34,10 @@
 #define noLuaClosure(f)		((f) == NULL || (f)->c.tt == LUA_TCCL)
 
 
+/* Active Lua function (given call info) */
+#define ci_func(ci)		(clLvalue((ci)->func))
+
+
 static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name);
 
 
@@ -49,6 +53,22 @@
 
 
 /*
+** If function yielded, its 'func' can be in the 'extra' field. The
+** next function restores 'func' to its correct value for debugging
+** purposes. (It exchanges 'func' and 'extra'; so, when called again,
+** after debugging, it also "re-restores" ** 'func' to its altered value.
+*/
+static void swapextra (lua_State *L) {
+  if (L->status == LUA_YIELD) {
+    CallInfo *ci = L->ci;  /* get function that yielded */
+    StkId temp = ci->func;  /* exchange its 'func' and 'extra' values */
+    ci->func = restorestack(L, ci->extra);
+    ci->extra = savestack(L, temp);
+  }
+}
+
+
+/*
 ** this function can be called asynchronous (e.g. during a signal)
 */
 LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
@@ -106,7 +126,7 @@
 
 static const char *findvararg (CallInfo *ci, int n, StkId *pos) {
   int nparams = clLvalue(ci->func)->p->numparams;
-  if (n >= ci->u.l.base - ci->func - nparams)
+  if (n >= cast_int(ci->u.l.base - ci->func) - nparams)
     return NULL;  /* no such vararg */
   else {
     *pos = ci->func + nparams + n;
@@ -144,6 +164,7 @@
 LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
   const char *name;
   lua_lock(L);
+  swapextra(L);
   if (ar == NULL) {  /* information about non-active function? */
     if (!isLfunction(L->top - 1))  /* not a Lua function? */
       name = NULL;
@@ -151,26 +172,30 @@
       name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0);
   }
   else {  /* active function; get information through 'ar' */
-    StkId pos = 0;  /* to avoid warnings */
+    StkId pos = NULL;  /* to avoid warnings */
     name = findlocal(L, ar->i_ci, n, &pos);
     if (name) {
       setobj2s(L, L->top, pos);
       api_incr_top(L);
     }
   }
+  swapextra(L);
   lua_unlock(L);
   return name;
 }
 
 
 LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
-  StkId pos = 0;  /* to avoid warnings */
-  const char *name = findlocal(L, ar->i_ci, n, &pos);
+  StkId pos = NULL;  /* to avoid warnings */
+  const char *name;
   lua_lock(L);
+  swapextra(L);
+  name = findlocal(L, ar->i_ci, n, &pos);
   if (name) {
     setobjs2s(L, pos, L->top - 1);
     L->top--;  /* pop value */
   }
+  swapextra(L);
   lua_unlock(L);
   return name;
 }
@@ -270,10 +295,11 @@
   CallInfo *ci;
   StkId func;
   lua_lock(L);
+  swapextra(L);
   if (*what == '>') {
     ci = NULL;
     func = L->top - 1;
-    api_check(ttisfunction(func), "function expected");
+    api_check(L, ttisfunction(func), "function expected");
     what++;  /* skip the '>' */
     L->top--;  /* pop function */
   }
@@ -288,6 +314,7 @@
     setobjs2s(L, L->top, func);
     api_incr_top(L);
   }
+  swapextra(L);  /* correct before option 'L', which can raise a mem. error */
   if (strchr(what, 'L'))
     collectvalidlines(L, cl);
   lua_unlock(L);
@@ -572,19 +599,16 @@
 }
 
 
-static void addinfo (lua_State *L, const char *msg) {
-  CallInfo *ci = L->ci;
-  if (isLua(ci)) {  /* is Lua code? */
-    char buff[LUA_IDSIZE];  /* add file:line information */
-    int line = currentline(ci);
-    TString *src = ci_func(ci)->p->source;
-    if (src)
-      luaO_chunkid(buff, getstr(src), LUA_IDSIZE);
-    else {  /* no source available; use "?" instead */
-      buff[0] = '?'; buff[1] = '\0';
-    }
-    luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
+/* add src:line information to 'msg' */
+const char *luaG_addinfo (lua_State *L, const char *msg, TString *src,
+                                        int line) {
+  char buff[LUA_IDSIZE];
+  if (src)
+    luaO_chunkid(buff, getstr(src), LUA_IDSIZE);
+  else {  /* no source available; use "?" instead */
+    buff[0] = '?'; buff[1] = '\0';
   }
+  return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
 }
 
 
@@ -594,17 +618,21 @@
     setobjs2s(L, L->top, L->top - 1);  /* move argument */
     setobjs2s(L, L->top - 1, errfunc);  /* push function */
     L->top++;  /* assume EXTRA_STACK */
-    luaD_call(L, L->top - 2, 1, 0);  /* call it */
+    luaD_callnoyield(L, L->top - 2, 1);  /* call it */
   }
   luaD_throw(L, LUA_ERRRUN);
 }
 
 
 l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
+  CallInfo *ci = L->ci;
+  const char *msg;
   va_list argp;
   va_start(argp, fmt);
-  addinfo(L, luaO_pushvfstring(L, fmt, argp));
+  msg = luaO_pushvfstring(L, fmt, argp);  /* format message */
   va_end(argp);
+  if (isLua(ci))  /* if Lua function, add source:line information */
+    luaG_addinfo(L, msg, ci_func(ci)->p->source, currentline(ci));
   luaG_errormsg(L);
 }
 
@@ -612,9 +640,11 @@
 void luaG_traceexec (lua_State *L) {
   CallInfo *ci = L->ci;
   lu_byte mask = L->hookmask;
-  int counthook = ((mask & LUA_MASKCOUNT) && L->hookcount == 0);
+  int counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT));
   if (counthook)
     resethookcount(L);  /* reset count */
+  else if (!(mask & LUA_MASKLINE))
+    return;  /* no line hook and count != 0; nothing to be done */
   if (ci->callstatus & CIST_HOOKYIELD) {  /* called hook last time? */
     ci->callstatus &= ~CIST_HOOKYIELD;  /* erase mark */
     return;  /* do not call hook again (VM yielded, so it did not move) */

=== modified file 'src/third_party/eris/ldebug.h'
--- src/third_party/eris/ldebug.h	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/ldebug.h	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.h,v 2.12 2014/11/10 14:46:05 roberto Exp $
+** $Id: ldebug.h,v 2.14 2015/05/22 17:45:56 roberto Exp $
 ** Auxiliary functions from Debug Interface module
 ** See Copyright Notice in lua.h
 */
@@ -17,9 +17,6 @@
 
 #define resethookcount(L)	(L->hookcount = L->basehookcount)
 
-/* Active Lua function (given call info) */
-#define ci_func(ci)		(clLvalue((ci)->func))
-
 
 LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o,
                                                 const char *opname);
@@ -33,6 +30,8 @@
 LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1,
                                                  const TValue *p2);
 LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...);
+LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg,
+                                                  TString *src, int line);
 LUAI_FUNC l_noret luaG_errormsg (lua_State *L);
 LUAI_FUNC void luaG_traceexec (lua_State *L);
 

=== modified file 'src/third_party/eris/ldo.c'
--- src/third_party/eris/ldo.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/ldo.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 2.135 2014/11/11 17:13:39 roberto Exp $
+** $Id: ldo.c,v 2.150 2015/11/19 19:16:22 roberto Exp $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -150,6 +150,11 @@
 /* }====================================================== */
 
 
+/*
+** {==================================================================
+** Stack reallocation
+** ===================================================================
+*/
 static void correctstack (lua_State *L, TValue *oldstack) {
   CallInfo *ci;
   UpVal *up;
@@ -221,12 +226,20 @@
     luaE_freeCI(L);  /* free all CIs (list grew because of an error) */
   else
     luaE_shrinkCI(L);  /* shrink list */
-  if (inuse > LUAI_MAXSTACK ||  /* still handling stack overflow? */
-      goodsize >= L->stacksize)  /* would grow instead of shrink? */
-    condmovestack(L);  /* don't change stack (change only for debugging) */
-  else
+  if (inuse <= LUAI_MAXSTACK &&  /* not handling stack overflow? */
+      goodsize < L->stacksize)  /* trying to shrink? */
     luaD_reallocstack(L, goodsize);  /* shrink it */
-}
+  else
+    condmovestack(L,,);  /* don't change stack (change only for debugging) */
+}
+
+
+void luaD_inctop (lua_State *L) {
+  luaD_checkstack(L, 1);
+  L->top++;
+}
+
+/* }================================================================== */
 
 
 void luaD_hook (lua_State *L, int event, int line) {
@@ -273,15 +286,15 @@
   int i;
   int nfixargs = p->numparams;
   StkId base, fixed;
-  lua_assert(actual >= nfixargs);
   /* move fixed parameters to final position */
-  luaD_checkstack(L, p->maxstacksize);  /* check again for new 'base' */
   fixed = L->top - actual;  /* first fixed argument */
   base = L->top;  /* final position of first argument */
-  for (i=0; i<nfixargs; i++) {
+  for (i = 0; i < nfixargs && i < actual; i++) {
     setobjs2s(L, L->top++, fixed + i);
-    setnilvalue(fixed + i);
+    setnilvalue(fixed + i);  /* erase original copy (for GC) */
   }
+  for (; i < nfixargs; i++)
+    setnilvalue(L->top++);  /* complete missing arguments */
   return base;
 }
 
@@ -308,70 +321,75 @@
 #define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L)))
 
 
+/* macro to check stack size, preserving 'p' */
+#define checkstackp(L,n,p)  \
+  luaD_checkstackaux(L, n, \
+    ptrdiff_t t__ = savestack(L, p);  /* save 'p' */ \
+    luaC_checkGC(L),  /* stack grow uses memory */ \
+    p = restorestack(L, t__))  /* 'pos' part: restore 'p' */
+
+
 /*
-** returns true if function has been executed (C function)
+** Prepares a function call: checks the stack, creates a new CallInfo
+** entry, fills in the relevant information, calls hook if needed.
+** If function is a C function, does the call, too. (Otherwise, leave
+** the execution ('luaV_execute') to the caller, to allow stackless
+** calls.) Returns true iff function has been executed (C function).
 */
 int luaD_precall (lua_State *L, StkId func, int nresults) {
   lua_CFunction f;
   CallInfo *ci;
-  int n;  /* number of arguments (Lua) or returns (C) */
-  ptrdiff_t funcr = savestack(L, func);
   switch (ttype(func)) {
+    case LUA_TCCL:  /* C closure */
+      f = clCvalue(func)->f;
+      goto Cfunc;
     case LUA_TLCF:  /* light C function */
       f = fvalue(func);
-      goto Cfunc;
-    case LUA_TCCL: {  /* C closure */
-      f = clCvalue(func)->f;
-     Cfunc:
-      luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */
+     Cfunc: {
+      int n;  /* number of returns */
+      checkstackp(L, LUA_MINSTACK, func);  /* ensure minimum stack size */
       ci = next_ci(L);  /* now 'enter' new function */
       ci->nresults = nresults;
-      ci->func = restorestack(L, funcr);
+      ci->func = func;
       ci->top = L->top + LUA_MINSTACK;
       lua_assert(ci->top <= L->stack_last);
       ci->callstatus = 0;
-      luaC_checkGC(L);  /* stack grow uses memory */
       if (L->hookmask & LUA_MASKCALL)
         luaD_hook(L, LUA_HOOKCALL, -1);
       lua_unlock(L);
       n = (*f)(L);  /* do the actual call */
       lua_lock(L);
       api_checknelems(L, n);
-      luaD_poscall(L, L->top - n);
+      luaD_poscall(L, ci, L->top - n, n);
       return 1;
     }
     case LUA_TLCL: {  /* Lua function: prepare its call */
       StkId base;
       Proto *p = clLvalue(func)->p;
-      n = cast_int(L->top - func) - 1;  /* number of real arguments */
-      luaD_checkstack(L, p->maxstacksize);
-      for (; n < p->numparams; n++)
-        setnilvalue(L->top++);  /* complete missing arguments */
-      if (!p->is_vararg) {
-        func = restorestack(L, funcr);
+      int n = cast_int(L->top - func) - 1;  /* number of real arguments */
+      int fsize = p->maxstacksize;  /* frame size */
+      checkstackp(L, fsize, func);
+      if (p->is_vararg != 1) {  /* do not use vararg? */
+        for (; n < p->numparams; n++)
+          setnilvalue(L->top++);  /* complete missing arguments */
         base = func + 1;
       }
-      else {
+      else
         base = adjust_varargs(L, p, n);
-        func = restorestack(L, funcr);  /* previous call can change stack */
-      }
       ci = next_ci(L);  /* now 'enter' new function */
       ci->nresults = nresults;
       ci->func = func;
       ci->u.l.base = base;
-      ci->top = base + p->maxstacksize;
+      L->top = ci->top = base + fsize;
       lua_assert(ci->top <= L->stack_last);
       ci->u.l.savedpc = p->code;  /* starting point */
       ci->callstatus = CIST_LUA;
-      L->top = ci->top;
-      luaC_checkGC(L);  /* stack grow uses memory */
       if (L->hookmask & LUA_MASKCALL)
         callhook(L, ci);
       return 0;
     }
     default: {  /* not a function */
-      luaD_checkstack(L, 1);  /* ensure space for metamethod */
-      func = restorestack(L, funcr);  /* previous call may change stack */
+      checkstackp(L, 1, func);  /* ensure space for metamethod */
       tryfuncTM(L, func);  /* try to get '__call' metamethod */
       return luaD_precall(L, func, nresults);  /* now it must be a function */
     }
@@ -379,10 +397,57 @@
 }
 
 
-int luaD_poscall (lua_State *L, StkId firstResult) {
+/*
+** Given 'nres' results at 'firstResult', move 'wanted' of them to 'res'.
+** Handle most typical cases (zero results for commands, one result for
+** expressions, multiple results for tail calls/single parameters)
+** separated.
+*/
+static int moveresults (lua_State *L, const TValue *firstResult, StkId res,
+                                      int nres, int wanted) {
+  switch (wanted) {  /* handle typical cases separately */
+    case 0: break;  /* nothing to move */
+    case 1: {  /* one result needed */
+      if (nres == 0)   /* no results? */
+        firstResult = luaO_nilobject;  /* adjust with nil */
+      setobjs2s(L, res, firstResult);  /* move it to proper place */
+      break;
+    }
+    case LUA_MULTRET: {
+      int i;
+      for (i = 0; i < nres; i++)  /* move all results to correct place */
+        setobjs2s(L, res + i, firstResult + i);
+      L->top = res + nres;
+      return 0;  /* wanted == LUA_MULTRET */
+    }
+    default: {
+      int i;
+      if (wanted <= nres) {  /* enough results? */
+        for (i = 0; i < wanted; i++)  /* move wanted results to correct place */
+          setobjs2s(L, res + i, firstResult + i);
+      }
+      else {  /* not enough results; use all of them plus nils */
+        for (i = 0; i < nres; i++)  /* move all results to correct place */
+          setobjs2s(L, res + i, firstResult + i);
+        for (; i < wanted; i++)  /* complete wanted number of results */
+          setnilvalue(res + i);
+      }
+      break;
+    }
+  }
+  L->top = res + wanted;  /* top points after the last result */
+  return 1;
+}
+
+
+/*
+** Finishes a function call: calls hook if necessary, removes CallInfo,
+** moves current number of results to proper place; returns 0 iff call
+** wanted multiple (variable number of) results.
+*/
+int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) {
   StkId res;
-  int wanted, i;
-  CallInfo *ci = L->ci;
+  int wanted = ci->nresults;
   if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) {
     if (L->hookmask & LUA_MASKRET) {
       ptrdiff_t fr = savestack(L, firstResult);  /* hook may change stack */
@@ -392,15 +457,24 @@
     L->oldpc = ci->previous->u.l.savedpc;  /* 'oldpc' for caller function */
   }
   res = ci->func;  /* res == final position of 1st result */
-  wanted = ci->nresults;
-  L->ci = ci = ci->previous;  /* back to caller */
-  /* move results to correct place */
-  for (i = wanted; i != 0 && firstResult < L->top; i--)
-    setobjs2s(L, res++, firstResult++);
-  while (i-- > 0)
-    setnilvalue(res++);
-  L->top = res;
-  return (wanted - LUA_MULTRET);  /* 0 iff wanted == LUA_MULTRET */
+  L->ci = ci->previous;  /* back to caller */
+  /* move results to proper place */
+  return moveresults(L, firstResult, res, nres, wanted);
+}
+
+
+/*
+** Check appropriate error for stack overflow ("regular" overflow or
+** overflow while handling stack overflow). If 'nCalls' is larger than
+** LUAI_MAXCCALLS (which means it is handling a "regular" overflow) but
+** smaller than 9/8 of LUAI_MAXCCALLS, does not report an error (to
+** allow overflow handling to work)
+*/
+static void stackerror (lua_State *L) {
+  if (L->nCcalls == LUAI_MAXCCALLS)
+    luaG_runerror(L, "C stack overflow");
+  else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
+    luaD_throw(L, LUA_ERRERR);  /* error while handing stack error */
 }
 
 
@@ -410,22 +484,26 @@
 ** When returns, all the results are on the stack, starting at the original
 ** function position.
 */
-void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) {
-  if (++L->nCcalls >= LUAI_MAXCCALLS) {
-    if (L->nCcalls == LUAI_MAXCCALLS)
-      luaG_runerror(L, "C stack overflow");
-    else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
-      luaD_throw(L, LUA_ERRERR);  /* error while handing stack error */
-  }
-  if (!allowyield) L->nny++;
+void luaD_call (lua_State *L, StkId func, int nResults) {
+  if (++L->nCcalls >= LUAI_MAXCCALLS)
+    stackerror(L);
   if (!luaD_precall(L, func, nResults))  /* is a Lua function? */
     luaV_execute(L);  /* call it */
-  if (!allowyield) L->nny--;
   L->nCcalls--;
 }
 
 
 /*
+** Similar to 'luaD_call', but does not allow yields during the call
+*/
+void luaD_callnoyield (lua_State *L, StkId func, int nResults) {
+  L->nny++;
+  luaD_call(L, func, nResults);
+  L->nny--;
+}
+
+
+/*
 ** Completes the execution of an interrupted C function, calling its
 ** continuation function.
 */
@@ -449,7 +527,7 @@
   lua_lock(L);
   api_checknelems(L, n);
   /* finish 'luaD_precall' */
-  luaD_poscall(L, L->top - n);
+  luaD_poscall(L, ci, L->top - n, n);
 }
 
 
@@ -533,7 +611,8 @@
 */
 static void resume (lua_State *L, void *ud) {
   int nCcalls = L->nCcalls;
-  StkId firstArg = cast(StkId, ud);
+  int n = *(cast(int*, ud));  /* number of arguments */
+  StkId firstArg = L->top - n;  /* first argument */
   CallInfo *ci = L->ci;
   if (nCcalls >= LUAI_MAXCCALLS)
     resume_error(L, "C stack overflow", firstArg);
@@ -553,14 +632,13 @@
       luaV_execute(L);  /* just continue running Lua code */
     else {  /* 'common' yield */
       if (ci->u.c.k != NULL) {  /* does it have a continuation function? */
-        int n;
         lua_unlock(L);
         n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */
         lua_lock(L);
         api_checknelems(L, n);
         firstArg = L->top - n;  /* yield results come from continuation */
       }
-      luaD_poscall(L, firstArg);  /* finish 'luaD_precall' */
+      luaD_poscall(L, ci, firstArg, n);  /* finish 'luaD_precall' */
     }
     unroll(L, NULL);  /* run continuation */
   }
@@ -570,13 +648,13 @@
 
 LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
   int status;
-  int oldnny = L->nny;  /* save "number of non-yieldable" calls */
+  unsigned short oldnny = L->nny;  /* save "number of non-yieldable" calls */
   lua_lock(L);
   luai_userstateresume(L, nargs);
   L->nCcalls = (from) ? from->nCcalls + 1 : 1;
   L->nny = 0;  /* allow yields */
   api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
-  status = luaD_rawrunprotected(L, resume, L->top - nargs);
+  status = luaD_rawrunprotected(L, resume, &nargs);
   if (status == -1)  /* error calling 'lua_resume'? */
     status = LUA_ERRRUN;
   else {  /* continue running after recoverable errors */
@@ -619,7 +697,7 @@
   L->status = LUA_YIELD;
   ci->extra = savestack(L, ci->func);  /* save current 'func' */
   if (isLua(ci)) {  /* inside a hook? */
-    api_check(k == NULL, "hooks cannot continue after yielding");
+    api_check(L, k == NULL, "hooks cannot continue after yielding");
   }
   else {
     if ((ci->u.c.k = k) != NULL)  /* is there a continuation? */
@@ -684,7 +762,7 @@
   int c = zgetc(p->z);  /* read first character */
   if (c == LUA_SIGNATURE[0]) {
     checkmode(L, p->mode, "binary");
-    cl = luaU_undump(L, p->z, &p->buff, p->name);
+    cl = luaU_undump(L, p->z, p->name);
   }
   else {
     checkmode(L, p->mode, "text");

=== modified file 'src/third_party/eris/ldo.h'
--- src/third_party/eris/ldo.h	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/ldo.h	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.h,v 2.21 2014/10/25 11:50:46 roberto Exp $
+** $Id: ldo.h,v 2.28 2015/11/23 11:29:43 roberto Exp $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -13,11 +13,21 @@
 #include "lzio.h"
 
 
-#define luaD_checkstack(L,n)	if (L->stack_last - L->top <= (n)) \
-				    luaD_growstack(L, n); else condmovestack(L);
-
-
-#define incr_top(L) {L->top++; luaD_checkstack(L,0);}
+/*
+** Macro to check stack size and grow stack if needed.  Parameters
+** 'pre'/'pos' allow the macro to preserve a pointer into the
+** stack across reallocations, doing the work only when needed.
+** 'condmovestack' is used in heavy tests to force a stack reallocation
+** at every check.
+*/
+#define luaD_checkstackaux(L,n,pre,pos)  \
+	if (L->stack_last - L->top <= (n)) \
+	  { pre; luaD_growstack(L, n); pos; } else { condmovestack(L,pre,pos); }
+
+/* In general, 'pre'/'pos' are empty (nothing to save) */
+#define luaD_checkstack(L,n)	luaD_checkstackaux(L,n,,)
+
+
 
 #define savestack(L,p)		((char *)(p) - (char *)L->stack)
 #define restorestack(L,n)	((TValue *)((char *)L->stack + (n)))
@@ -30,14 +40,16 @@
                                                   const char *mode);
 LUAI_FUNC void luaD_hook (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,
-                                        int allowyield);
+LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
+LUAI_FUNC void luaD_callnoyield (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 int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult,
+                                          int nres);
 LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
 LUAI_FUNC void luaD_growstack (lua_State *L, int n);
 LUAI_FUNC void luaD_shrinkstack (lua_State *L);
+LUAI_FUNC void luaD_inctop (lua_State *L);
 
 LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode);
 LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);

=== modified file 'src/third_party/eris/ldump.c'
--- src/third_party/eris/ldump.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/ldump.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: ldump.c,v 2.34 2014/11/02 19:19:04 roberto Exp $
+** $Id: ldump.c,v 2.37 2015/10/08 15:53:49 roberto Exp $
 ** save precompiled Lua chunks
 ** See Copyright Notice in lua.h
 */
@@ -38,7 +38,7 @@
 
 
 static void DumpBlock (const void *b, size_t size, DumpState *D) {
-  if (D->status == 0) {
+  if (D->status == 0 && size > 0) {
     lua_unlock(D->L);
     D->status = (*D->writer)(D->L, b, size, D->data);
     lua_lock(D->L);
@@ -74,14 +74,15 @@
   if (s == NULL)
     DumpByte(0, D);
   else {
-    size_t size = s->len + 1;  /* include trailing '\0' */
+    size_t size = tsslen(s) + 1;  /* include trailing '\0' */
+    const char *str = getstr(s);
     if (size < 0xFF)
       DumpByte(cast_int(size), D);
     else {
       DumpByte(0xFF, D);
       DumpVar(size, D);
     }
-    DumpVector(getstr(s), size - 1, D);  /* no need to save '\0' */
+    DumpVector(str, size - 1, D);  /* no need to save '\0' */
   }
 }
 

=== modified file 'src/third_party/eris/lfunc.h'
--- src/third_party/eris/lfunc.h	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lfunc.h	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lfunc.h,v 2.14 2014/06/19 18:27:20 roberto Exp $
+** $Id: lfunc.h,v 2.15 2015/01/13 15:49:11 roberto Exp $
 ** Auxiliary functions to manipulate prototypes and closures
 ** See Copyright Notice in lua.h
 */
@@ -23,6 +23,13 @@
 
 
 /*
+** maximum number of upvalues in a closure (both C and Lua). (Value
+** must fit in a VM register.)
+*/
+#define MAXUPVAL	255
+
+
+/*
 ** Upvalues for Lua closures
 */
 struct UpVal {

=== modified file 'src/third_party/eris/lgc.c'
--- src/third_party/eris/lgc.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lgc.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 2.201 2014/12/20 13:58:15 roberto Exp $
+** $Id: lgc.c,v 2.210 2015/11/03 18:10:44 roberto Exp $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -83,8 +83,13 @@
 #define markvalue(g,o) { checkconsistency(o); \
   if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); }
 
-#define markobject(g,t) \
-  { if ((t) && iswhite(t)) reallymarkobject(g, obj2gco(t)); }
+#define markobject(g,t)	{ if (iswhite(t)) reallymarkobject(g, obj2gco(t)); }
+
+/*
+** mark an object that can be NULL (either because it is really optional,
+** or it was stripped as debug info, or inside an uncompleted structure)
+*/
+#define markobjectN(g,t)	{ if (t) markobject(g,t); }
 
 static void reallymarkobject (global_State *g, GCObject *o);
 
@@ -109,8 +114,13 @@
 
 
 /*
-** if key is not marked, mark its entry as dead (therefore removing it
-** from the table)
+** If key is not marked, mark its entry as dead. This allows key to be
+** collected, but keeps its entry in the table.  A dead node is needed
+** when Lua looks up for a key (it may be part of a chain) and when
+** traversing a weak table (key might be removed from the table during
+** traversal). Other places never manipulate dead keys, because its
+** associated nil value is enough to signal that the entry is logically
+** empty.
 */
 static void removeentry (Node *n) {
   lua_assert(ttisnil(gval(n)));
@@ -226,15 +236,19 @@
  reentry:
   white2gray(o);
   switch (o->tt) {
-    case LUA_TSHRSTR:
+    case LUA_TSHRSTR: {
+      gray2black(o);
+      g->GCmemtrav += sizelstring(gco2ts(o)->shrlen);
+      break;
+    }
     case LUA_TLNGSTR: {
       gray2black(o);
-      g->GCmemtrav += sizestring(gco2ts(o));
+      g->GCmemtrav += sizelstring(gco2ts(o)->u.lnglen);
       break;
     }
     case LUA_TUSERDATA: {
       TValue uvalue;
-      markobject(g, gco2u(o)->metatable);  /* mark its metatable */
+      markobjectN(g, gco2u(o)->metatable);  /* mark its metatable */
       gray2black(o);
       g->GCmemtrav += sizeudata(gco2u(o));
       getuservalue(g->mainthread, gco2u(o), &uvalue);
@@ -275,7 +289,7 @@
 static void markmt (global_State *g) {
   int i;
   for (i=0; i < LUA_NUMTAGS; i++)
-    markobject(g, g->mt[i]);
+    markobjectN(g, g->mt[i]);
 }
 
 
@@ -437,7 +451,7 @@
 static lu_mem traversetable (global_State *g, Table *h) {
   const char *weakkey, *weakvalue;
   const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
-  markobject(g, h->metatable);
+  markobjectN(g, h->metatable);
   if (mode && ttisstring(mode) &&  /* is there a weak mode? */
       ((weakkey = strchr(svalue(mode), 'k')),
        (weakvalue = strchr(svalue(mode), 'v')),
@@ -457,19 +471,24 @@
 }
 
 
+/*
+** Traverse a prototype. (While a prototype is being build, its
+** arrays can be larger than needed; the extra slots are filled with
+** NULL, so the use of 'markobjectN')
+*/
 static int traverseproto (global_State *g, Proto *f) {
   int i;
   if (f->cache && iswhite(f->cache))
     f->cache = NULL;  /* allow cache to be collected */
-  markobject(g, f->source);
+  markobjectN(g, f->source);
   for (i = 0; i < f->sizek; i++)  /* mark literals */
     markvalue(g, &f->k[i]);
   for (i = 0; i < f->sizeupvalues; i++)  /* mark upvalue names */
-    markobject(g, f->upvalues[i].name);
+    markobjectN(g, f->upvalues[i].name);
   for (i = 0; i < f->sizep; i++)  /* mark nested protos */
-    markobject(g, f->p[i]);
+    markobjectN(g, f->p[i]);
   for (i = 0; i < f->sizelocvars; i++)  /* mark local-variable names */
-    markobject(g, f->locvars[i].varname);
+    markobjectN(g, f->locvars[i].varname);
   return sizeof(Proto) + sizeof(Instruction) * f->sizecode +
                          sizeof(Proto *) * f->sizep +
                          sizeof(TValue) * f->sizek +
@@ -494,7 +513,7 @@
 */
 static lu_mem traverseLclosure (global_State *g, LClosure *cl) {
   int i;
-  markobject(g, cl->p);  /* mark its prototype */
+  markobjectN(g, cl->p);  /* mark its prototype */
   for (i = 0; i < cl->nupvalues; i++) {  /* mark its upvalues */
     UpVal *uv = cl->upvals[i];
     if (uv != NULL) {
@@ -528,7 +547,8 @@
   }
   else if (g->gckind != KGC_EMERGENCY)
     luaD_shrinkstack(th); /* do not change stack in emergency cycle */
-  return (sizeof(lua_State) + sizeof(TValue) * th->stacksize);
+  return (sizeof(lua_State) + sizeof(TValue) * th->stacksize +
+          sizeof(CallInfo) * th->nci);
 }
 
 
@@ -689,9 +709,10 @@
     case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break;
     case LUA_TSHRSTR:
       luaS_remove(L, gco2ts(o));  /* remove it from hash table */
-      /* go through */
+      luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen));
+      break;
     case LUA_TLNGSTR: {
-      luaM_freemem(L, o, sizestring(gco2ts(o)));
+      luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen));
       break;
     }
     default: lua_assert(0);
@@ -754,12 +775,11 @@
 */
 
 /*
-** If possible, free concatenation buffer and shrink string table
+** If possible, shrink string table
 */
 static void checkSizes (lua_State *L, global_State *g) {
   if (g->gckind != KGC_EMERGENCY) {
     l_mem olddebt = g->GCdebt;
-    luaZ_freebuffer(L, &g->buff);  /* free concatenation buffer */
     if (g->strt.nuse < g->strt.size / 4)  /* string table too big? */
       luaS_resize(L, g->strt.size / 2);  /* shrink it a little */
     g->GCestimate += g->GCdebt - olddebt;  /* update estimate */
@@ -782,7 +802,7 @@
 
 static void dothecall (lua_State *L, void *ud) {
   UNUSED(ud);
-  luaD_call(L, L->top - 2, 0, 0);
+  luaD_callnoyield(L, L->top - 2, 0);
 }
 
 
@@ -1002,6 +1022,7 @@
   /* clear values from resurrected weak tables */
   clearvalues(g, g->weak, origweak);
   clearvalues(g, g->allweak, origall);
+  luaS_clearcache(g);
   g->currentwhite = cast_byte(otherwhite(g));  /* flip current white */
   work += g->GCmemtrav;  /* complete counting */
   return work;  /* estimate of memory marked by 'atomic' */
@@ -1098,9 +1119,12 @@
 static l_mem getdebt (global_State *g) {
   l_mem debt = g->GCdebt;
   int stepmul = g->gcstepmul;
-  debt = (debt / STEPMULADJ) + 1;
-  debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM;
-  return debt;
+  if (debt <= 0) return 0;  /* minimal debt */
+  else {
+    debt = (debt / STEPMULADJ) + 1;
+    debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM;
+    return debt;
+  }
 }
 
 /*

=== modified file 'src/third_party/eris/lgc.h'
--- src/third_party/eris/lgc.h	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lgc.h	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.h,v 2.86 2014/10/25 11:50:46 roberto Exp $
+** $Id: lgc.h,v 2.90 2015/10/21 18:15:15 roberto Exp $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -101,26 +101,35 @@
 #define luaC_white(g)	cast(lu_byte, (g)->currentwhite & WHITEBITS)
 
 
-#define luaC_condGC(L,c) \
-	{if (G(L)->GCdebt > 0) {c;}; condchangemem(L);}
-#define luaC_checkGC(L)		luaC_condGC(L, luaC_step(L);)
-
-
-#define luaC_barrier(L,p,v) {  \
-	if (iscollectable(v) && isblack(p) && iswhite(gcvalue(v)))  \
-	luaC_barrier_(L,obj2gco(p),gcvalue(v)); }
-
-#define luaC_barrierback(L,p,v) {  \
-	if (iscollectable(v) && isblack(p) && iswhite(gcvalue(v)))  \
-	luaC_barrierback_(L,p); }
-
-#define luaC_objbarrier(L,p,o) {  \
-	if (isblack(p) && iswhite(o)) \
-		luaC_barrier_(L,obj2gco(p),obj2gco(o)); }
-
-#define luaC_upvalbarrier(L,uv) \
-  { if (iscollectable((uv)->v) && !upisopen(uv)) \
-         luaC_upvalbarrier_(L,uv); }
+/*
+** Does one step of collection when debt becomes positive. 'pre'/'pos'
+** allows some adjustments to be done only when needed. macro
+** 'condchangemem' is used only for heavy tests (forcing a full
+** GC cycle on every opportunity)
+*/
+#define luaC_condGC(L,pre,pos) \
+	{ if (G(L)->GCdebt > 0) { pre; luaC_step(L); pos;}; \
+	  condchangemem(L,pre,pos); }
+
+/* more often than not, 'pre'/'pos' are empty */
+#define luaC_checkGC(L)		luaC_condGC(L,,)
+
+
+#define luaC_barrier(L,p,v) (  \
+	(iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ?  \
+	luaC_barrier_(L,obj2gco(p),gcvalue(v)) : cast_void(0))
+
+#define luaC_barrierback(L,p,v) (  \
+	(iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \
+	luaC_barrierback_(L,p) : cast_void(0))
+
+#define luaC_objbarrier(L,p,o) (  \
+	(isblack(p) && iswhite(o)) ? \
+	luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0))
+
+#define luaC_upvalbarrier(L,uv) ( \
+	(iscollectable((uv)->v) && !upisopen(uv)) ? \
+         luaC_upvalbarrier_(L,uv) : cast_void(0))
 
 LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o);
 LUAI_FUNC void luaC_freeallobjects (lua_State *L);

=== modified file 'src/third_party/eris/liolib.c'
--- src/third_party/eris/liolib.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/liolib.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: liolib.c,v 2.142 2015/01/02 12:50:28 roberto Exp $
+** $Id: liolib.c,v 2.148 2015/11/23 11:36:11 roberto Exp $
 ** Standard I/O (and system) library
 ** See Copyright Notice in lua.h
 */
@@ -23,18 +23,24 @@
 #include "lualib.h"
 
 
-#if !defined(l_checkmode)
+
 
 /*
-** Check whether 'mode' matches '[rwa]%+?b?'.
 ** Change this macro to accept other modes for 'fopen' besides
 ** the standard ones.
 */
+#if !defined(l_checkmode)
+
+/* accepted extensions to 'mode' in 'fopen' */
+#if !defined(L_MODEEXT)
+#define L_MODEEXT	"b"
+#endif
+
+/* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */
 #define l_checkmode(mode) \
 	(*mode != '\0' && strchr("rwa", *(mode++)) != NULL &&	\
-	(*mode != '+' || ++mode) &&  /* skip if char is '+' */	\
-	(*mode != 'b' || ++mode) &&  /* skip if char is 'b' */	\
-	(*mode == '\0'))
+	(*mode != '+' || (++mode, 1)) &&  /* skip if char is '+' */	\
+	(strspn(mode, L_MODEEXT) == strlen(mode)))
 
 #endif
 
@@ -176,7 +182,7 @@
 /*
 ** When creating file handles, always creates a 'closed' file handle
 ** before opening the actual file; so, if there is a memory error, the
-** file is not left opened.
+** handle is in a consistent state.
 */
 static LStream *newprefile (lua_State *L) {
   LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream));
@@ -318,8 +324,15 @@
 static int io_readline (lua_State *L);
 
 
+/*
+** maximum number of arguments to 'f:lines'/'io.lines' (it + 3 must fit
+** in the limit for upvalues of a closure)
+*/
+#define MAXARGLINE	250
+
 static void aux_lines (lua_State *L, int toclose) {
   int n = lua_gettop(L) - 1;  /* number of arguments to read */
+  luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments");
   lua_pushinteger(L, n);  /* number of arguments to read */
   lua_pushboolean(L, toclose);  /* close/not close file when finished */
   lua_rotate(L, 2, 2);  /* move 'n' and 'toclose' to their positions */
@@ -410,12 +423,6 @@
 }
 
 
-/* access to locale "radix character" (decimal point) */
-#if !defined(l_getlocaledecpoint)
-#define l_getlocaledecpoint()     (localeconv()->decimal_point[0])
-#endif
-
-
 /*
 ** Read a number: first reads a valid prefix of a numeral into a buffer.
 ** Then it calls 'lua_stringtonumber' to check whether the format is
@@ -425,9 +432,10 @@
   RN rn;
   int count = 0;
   int hex = 0;
-  char decp[2] = ".";
+  char decp[2];
   rn.f = f; rn.n = 0;
-  decp[0] = l_getlocaledecpoint();  /* get decimal point from locale */
+  decp[0] = lua_getlocaledecpoint();  /* get decimal point from locale */
+  decp[1] = '\0';
   l_lockfile(rn.f);
   do { rn.c = l_getc(rn.f); } while (isspace(rn.c));  /* skip spaces */
   test2(&rn, "-+");  /* optional signal */
@@ -457,7 +465,7 @@
 static int test_eof (lua_State *L, FILE *f) {
   int c = getc(f);
   ungetc(c, f);  /* no-op when c == EOF */
-  lua_pushlstring(L, NULL, 0);
+  lua_pushliteral(L, "");
   return (c != EOF);
 }
 
@@ -467,7 +475,7 @@
   int c = '\0';
   luaL_buffinit(L, &b);
   while (c != EOF && c != '\n') {  /* repeat until end of line */
-    char *buff = luaL_prepbuffer(&b);  /* pre-allocate buffer */
+    char *buff = luaL_prepbuffer(&b);  /* preallocate buffer */
     int i = 0;
     l_lockfile(f);  /* no memory errors can happen inside the lock */
     while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n')
@@ -488,7 +496,7 @@
   luaL_Buffer b;
   luaL_buffinit(L, &b);
   do {  /* read file in chunks of LUAL_BUFFERSIZE bytes */
-    char *p = luaL_prepbuffsize(&b, LUAL_BUFFERSIZE);
+    char *p = luaL_prepbuffer(&b);
     nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f);
     luaL_addsize(&b, nr);
   } while (nr == LUAL_BUFFERSIZE);

=== modified file 'src/third_party/eris/llex.c'
--- src/third_party/eris/llex.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/llex.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: llex.c,v 2.89 2014/11/14 16:06:09 roberto Exp $
+** $Id: llex.c,v 2.95 2015/11/19 19:16:22 roberto Exp $
 ** Lexical Analyzer
 ** See Copyright Notice in lua.h
 */
@@ -16,6 +16,7 @@
 #include "lua.h"
 
 #include "lctype.h"
+#include "ldebug.h"
 #include "ldo.h"
 #include "lgc.h"
 #include "llex.h"
@@ -68,7 +69,7 @@
 
 void luaX_init (lua_State *L) {
   int i;
-  TString *e = luaS_new(L, LUA_ENV);  /* create env name */
+  TString *e = luaS_newliteral(L, LUA_ENV);  /* create env name */
   luaC_fix(L, obj2gco(e));  /* never collect this name */
   for (i=0; i<NUM_RESERVED; i++) {
     TString *ts = luaS_new(L, luaX_tokens[i]);
@@ -106,9 +107,7 @@
 
 
 static l_noret lexerror (LexState *ls, const char *msg, int token) {
-  char buff[LUA_IDSIZE];
-  luaO_chunkid(buff, getstr(ls->source), LUA_IDSIZE);
-  msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg);
+  msg = luaG_addinfo(ls->L, msg, ls->source, ls->linenumber);
   if (token)
     luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token));
   luaD_throw(ls->L, LUA_ERRSYNTAX);
@@ -172,7 +171,7 @@
   ls->linenumber = 1;
   ls->lastline = 1;
   ls->source = source;
-  ls->envn = luaS_new(L, LUA_ENV);  /* get env name */
+  ls->envn = luaS_newliteral(L, LUA_ENV);  /* get env name */
   luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER);  /* initialize buffer */
 }
 
@@ -221,22 +220,15 @@
 }
 
 
-#if !defined(l_getlocaledecpoint)
-#define l_getlocaledecpoint()	(localeconv()->decimal_point[0])
-#endif
-
-
-#define buff2num(b,o)	(luaO_str2num(luaZ_buffer(b), o) != 0)
-
 /*
 ** in case of format error, try to change decimal point separator to
 ** the one defined in the current locale and check again
 */
 static void trydecpoint (LexState *ls, TValue *o) {
   char old = ls->decpoint;
-  ls->decpoint = l_getlocaledecpoint();
+  ls->decpoint = lua_getlocaledecpoint();
   buffreplace(ls, old, ls->decpoint);  /* try new decimal separator */
-  if (!buff2num(ls->buff, o)) {
+  if (luaO_str2num(luaZ_buffer(ls->buff), o) == 0) {
     /* format error with correct decimal point: no more options */
     buffreplace(ls, ls->decpoint, '.');  /* undo change (for error message) */
     lexerror(ls, "malformed number", TK_FLT);
@@ -268,7 +260,7 @@
   }
   save(ls, '\0');
   buffreplace(ls, '.', ls->decpoint);  /* follow locale for decimal point */
-  if (!buff2num(ls->buff, &obj))  /* format error? */
+  if (luaO_str2num(luaZ_buffer(ls->buff), &obj) == 0)  /* format error? */
     trydecpoint(ls, &obj); /* try to update decimal point separator */
   if (ttisinteger(&obj)) {
     seminfo->i = ivalue(&obj);
@@ -283,8 +275,9 @@
 
 
 /*
-** skip a sequence '[=*[' or ']=*]' and return its number of '='s or
-** -1 if sequence is malformed
+** skip a sequence '[=*[' or ']=*]'; if sequence is well formed, return
+** its number of '='s; otherwise, return a negative number (-1 iff there
+** are no '='s after initial bracket)
 */
 static int skip_sep (LexState *ls) {
   int count = 0;
@@ -501,8 +494,9 @@
           read_long_string(ls, seminfo, sep);
           return TK_STRING;
         }
-        else if (sep == -1) return '[';
-        else lexerror(ls, "invalid long string delimiter", TK_STRING);
+        else if (sep != -1)  /* '[=...' missing second bracket */
+          lexerror(ls, "invalid long string delimiter", TK_STRING);
+        return '[';
       }
       case '=': {
         next(ls);

=== modified file 'src/third_party/eris/llimits.h'
--- src/third_party/eris/llimits.h	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/llimits.h	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: llimits.h,v 1.125 2014/12/19 13:30:23 roberto Exp $
+** $Id: llimits.h,v 1.141 2015/11/19 19:16:22 roberto Exp $
 ** Limits, basic types, and some other 'installation-dependent' definitions
 ** See Copyright Notice in lua.h
 */
@@ -52,11 +52,11 @@
 
 
 /*
-** conversion of pointer to integer:
+** conversion of pointer to unsigned integer:
 ** this is for hashing only; there is no problem if the integer
 ** cannot hold the whole pointer value
 */
-#define point2int(p)	((unsigned int)((size_t)(p) & UINT_MAX))
+#define point2uint(p)	((unsigned int)((size_t)(p) & UINT_MAX))
 
 
 
@@ -64,7 +64,13 @@
 #if defined(LUAI_USER_ALIGNMENT_T)
 typedef LUAI_USER_ALIGNMENT_T L_Umaxalign;
 #else
-typedef union { double u; void *s; lua_Integer i; long l; } L_Umaxalign;
+typedef union {
+  lua_Number n;
+  double u;
+  void *s;
+  lua_Integer i;
+  long l;
+} L_Umaxalign;
 #endif
 
 
@@ -78,7 +84,7 @@
 #if defined(lua_assert)
 #define check_exp(c,e)		(lua_assert(c), (e))
 /* to avoid problems with conditions too long */
-#define lua_longassert(c)	{ if (!(c)) lua_assert(0); }
+#define lua_longassert(c)	((c) ? (void)0 : lua_assert(0))
 #else
 #define lua_assert(c)		((void)0)
 #define check_exp(c,e)		(e)
@@ -88,22 +94,20 @@
 /*
 ** assertion for checking API calls
 */
-#if defined(LUA_USE_APICHECK)
-#include <assert.h>
-#define luai_apicheck(e)	assert(e)
-#else
-#define luai_apicheck(e)	lua_assert(e)
+#if !defined(luai_apicheck)
+#define luai_apicheck(l,e)	lua_assert(e)
 #endif
 
-
-#define api_check(e,msg)	luai_apicheck((e) && msg)
-
-
+#define api_check(l,e,msg)	luai_apicheck(l,(e) && msg)
+
+
+/* macro to avoid warnings about unused variables */
 #if !defined(UNUSED)
-#define UNUSED(x)	((void)(x))	/* to avoid warnings */
+#define UNUSED(x)	((void)(x))
 #endif
 
 
+/* type casts (a macro highlights casts in the code) */
 #define cast(t, exp)	((t)(exp))
 
 #define cast_void(i)	cast(void, (i))
@@ -149,11 +153,6 @@
 #define LUAI_MAXCCALLS		200
 #endif
 
-/*
-** maximum number of upvalues in a closure (both C and Lua). (Value
-** must fit in an unsigned char.)
-*/
-#define MAXUPVAL	UCHAR_MAX
 
 
 /*
@@ -168,10 +167,36 @@
 
 
 
-
-/* minimum size for the string table (must be power of 2) */
+/*
+** Maximum length for short strings, that is, strings that are
+** internalized. (Cannot be smaller than reserved words or tags for
+** metamethods, as these strings must be internalized;
+** #("function") = 8, #("__newindex") = 10.)
+*/
+#if !defined(LUAI_MAXSHORTLEN)
+#define LUAI_MAXSHORTLEN	40
+#endif
+
+
+/*
+** Initial size for the string table (must be power of 2).
+** The Lua core alone registers ~50 strings (reserved words +
+** metaevent keys + a few others). Libraries would typically add
+** a few dozens more.
+*/
 #if !defined(MINSTRTABSIZE)
-#define MINSTRTABSIZE	64	/* minimum size for "predefined" strings */
+#define MINSTRTABSIZE	128
+#endif
+
+
+/*
+** Size of cache for strings in the API. 'N' is the number of
+** sets (better be a prime) and "M" is the size of each set (M == 1
+** makes a direct cache.)
+*/
+#if !defined(STRCACHE_N)
+#define STRCACHE_N		53
+#define STRCACHE_M		2
 #endif
 
 
@@ -181,11 +206,19 @@
 #endif
 
 
+/*
+** macros that are executed whenever program enters the Lua core
+** ('lua_lock') and leaves the core ('lua_unlock')
+*/
 #if !defined(lua_lock)
 #define lua_lock(L)	((void) 0)
 #define lua_unlock(L)	((void) 0)
 #endif
 
+/*
+** macro executed during Lua functions at points where the
+** function can yield.
+*/
 #if !defined(luai_threadyield)
 #define luai_threadyield(L)	{lua_unlock(L); lua_lock(L);}
 #endif
@@ -223,20 +256,68 @@
 
 
 /*
+** The luai_num* macros define the primitive operations over numbers.
+*/
+
+/* floor division (defined as 'floor(a/b)') */
+#if !defined(luai_numidiv)
+#define luai_numidiv(L,a,b)     ((void)L, l_floor(luai_numdiv(L,a,b)))
+#endif
+
+/* float division */
+#if !defined(luai_numdiv)
+#define luai_numdiv(L,a,b)      ((a)/(b))
+#endif
+
+/*
+** modulo: defined as 'a - floor(a/b)*b'; this definition gives NaN when
+** 'b' is huge, but the result should be 'a'. 'fmod' gives the result of
+** 'a - trunc(a/b)*b', and therefore must be corrected when 'trunc(a/b)
+** ~= floor(a/b)'. That happens when the division has a non-integer
+** negative result, which is equivalent to the test below.
+*/
+#if !defined(luai_nummod)
+#define luai_nummod(L,a,b,m)  \
+  { (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); }
+#endif
+
+/* exponentiation */
+#if !defined(luai_numpow)
+#define luai_numpow(L,a,b)      ((void)L, l_mathop(pow)(a,b))
+#endif
+
+/* the others are quite standard operations */
+#if !defined(luai_numadd)
+#define luai_numadd(L,a,b)      ((a)+(b))
+#define luai_numsub(L,a,b)      ((a)-(b))
+#define luai_nummul(L,a,b)      ((a)*(b))
+#define luai_numunm(L,a)        (-(a))
+#define luai_numeq(a,b)         ((a)==(b))
+#define luai_numlt(a,b)         ((a)<(b))
+#define luai_numle(a,b)         ((a)<=(b))
+#define luai_numisnan(a)        (!luai_numeq((a), (a)))
+#endif
+
+
+
+
+
+/*
 ** macro to control inclusion of some hard tests on stack reallocation
 */
 #if !defined(HARDSTACKTESTS)
-#define condmovestack(L)	((void)0)
+#define condmovestack(L,pre,pos)	((void)0)
 #else
 /* realloc stack keeping its size */
-#define condmovestack(L)	luaD_reallocstack((L), (L)->stacksize)
+#define condmovestack(L,pre,pos)  \
+	{ int sz_ = (L)->stacksize; pre; luaD_reallocstack((L), sz_); pos; }
 #endif
 
 #if !defined(HARDMEMTESTS)
-#define condchangemem(L)	condmovestack(L)
+#define condchangemem(L,pre,pos)	((void)0)
 #else
-#define condchangemem(L)  \
-	((void)(!(G(L)->gcrunning) || (luaC_fullgc(L, 0), 1)))
+#define condchangemem(L,pre,pos)  \
+	{ if (G(L)->gcrunning) { pre; luaC_fullgc(L, 0); pos; } }
 #endif
 
 #endif

=== modified file 'src/third_party/eris/lmathlib.c'
--- src/third_party/eris/lmathlib.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lmathlib.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lmathlib.c,v 1.114 2014/12/27 20:32:26 roberto Exp $
+** $Id: lmathlib.c,v 1.117 2015/10/02 15:39:23 roberto Exp $
 ** Standard mathematical library
 ** See Copyright Notice in lua.h
 */
@@ -39,7 +39,7 @@
 static int math_abs (lua_State *L) {
   if (lua_isinteger(L, 1)) {
     lua_Integer n = lua_tointeger(L, 1);
-    if (n < 0) n = (lua_Integer)(0u - n);
+    if (n < 0) n = (lua_Integer)(0u - (lua_Unsigned)n);
     lua_pushinteger(L, n);
   }
   else
@@ -183,6 +183,9 @@
     res = l_mathop(log)(x);
   else {
     lua_Number base = luaL_checknumber(L, 2);
+#if !defined(LUA_USE_C89)
+    if (base == 2.0) res = l_mathop(log2)(x); else
+#endif
     if (base == 10.0) res = l_mathop(log10)(x);
     else res = l_mathop(log)(x)/l_mathop(log)(base);
   }
@@ -270,7 +273,7 @@
 
 static int math_randomseed (lua_State *L) {
   l_srand((unsigned int)(lua_Integer)luaL_checknumber(L, 1));
-  (void)rand(); /* discard first value to avoid undesirable correlations */
+  (void)l_rand(); /* discard first value to avoid undesirable correlations */
   return 0;
 }
 

=== modified file 'src/third_party/eris/lmem.c'
--- src/third_party/eris/lmem.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lmem.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lmem.c,v 1.89 2014/11/02 19:33:33 roberto Exp $
+** $Id: lmem.c,v 1.91 2015/03/06 19:45:54 roberto Exp $
 ** Interface to Memory Manager
 ** See Copyright Notice in lua.h
 */
@@ -85,10 +85,11 @@
 #endif
   newblock = (*g->frealloc)(g->ud, block, osize, nsize);
   if (newblock == NULL && nsize > 0) {
-    api_check( nsize > realosize,
-                 "realloc cannot fail when shrinking a block");
-    luaC_fullgc(L, 1);  /* try to free some memory... */
-    newblock = (*g->frealloc)(g->ud, block, osize, nsize);  /* try again */
+    lua_assert(nsize > realosize);  /* cannot fail when shrinking a block */
+    if (g->version) {  /* is state fully built? */
+      luaC_fullgc(L, 1);  /* try to free some memory... */
+      newblock = (*g->frealloc)(g->ud, block, osize, nsize);  /* try again */
+    }
     if (newblock == NULL)
       luaD_throw(L, LUA_ERRMEM);
   }

=== modified file 'src/third_party/eris/loadlib.c'
--- src/third_party/eris/loadlib.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/loadlib.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: loadlib.c,v 1.124 2015/01/05 13:51:39 roberto Exp $
+** $Id: loadlib.c,v 1.127 2015/11/23 11:30:45 roberto Exp $
 ** Dynamic library loader for Lua
 ** See Copyright Notice in lua.h
 **
@@ -14,6 +14,7 @@
 #include "lprefix.h"
 
 
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -136,8 +137,8 @@
 #include <dlfcn.h>
 
 /*
-** Macro to covert pointer to void* to pointer to function. This cast
-** is undefined according to ISO C, but POSIX assumes that it must work.
+** Macro to convert pointer-to-void* to pointer-to-function. This cast
+** is undefined according to ISO C, but POSIX assumes that it works.
 ** (The '__extension__' in gnu compilers is only to avoid warnings.)
 */
 #if defined(__GNUC__)
@@ -731,7 +732,7 @@
   int i;
   /* create 'searchers' table */
   lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0);
-  /* fill it with pre-defined searchers */
+  /* fill it with predefined searchers */
   for (i=0; searchers[i] != NULL; i++) {
     lua_pushvalue(L, -2);  /* set 'package' as upvalue for all searchers */
     lua_pushcclosure(L, searchers[i], 1);

=== modified file 'src/third_party/eris/lobject.c'
--- src/third_party/eris/lobject.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lobject.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.c,v 2.101 2014/12/26 14:43:45 roberto Exp $
+** $Id: lobject.c,v 2.108 2015/11/02 16:09:30 roberto Exp $
 ** Some generic functions over Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -10,6 +10,8 @@
 #include "lprefix.h"
 
 
+#include <locale.h>
+#include <math.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -39,8 +41,12 @@
 int luaO_int2fb (unsigned int x) {
   int e = 0;  /* exponent */
   if (x < 8) return x;
-  while (x >= 0x10) {
-    x = (x+1) >> 1;
+  while (x >= (8 << 4)) {  /* coarse steps */
+    x = (x + 0xf) >> 4;  /* x = ceil(x / 16) */
+    e += 4;
+  }
+  while (x >= (8 << 1)) {  /* fine steps */
+    x = (x + 1) >> 1;  /* x = ceil(x / 2) */
     e++;
   }
   return ((e+1) << 3) | (cast_int(x) - 8);
@@ -49,14 +55,15 @@
 
 /* converts back */
 int luaO_fb2int (int x) {
-  int e = (x >> 3) & 0x1f;
-  if (e == 0) return x;
-  else return ((x & 7) + 8) << (e - 1);
+  return (x < 8) ? x : ((x & 7) + 8) << ((x >> 3) - 1);
 }
 
 
+/*
+** Computes ceil(log2(x))
+*/
 int luaO_ceillog2 (unsigned int x) {
-  static const lu_byte log_2[256] = {
+  static const lu_byte log_2[256] = {  /* log_2[i] = ceil(log2(i - 1)) */
     0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
@@ -149,13 +156,13 @@
   }
   /* could not perform raw operation; try metamethod */
   lua_assert(L != NULL);  /* should not fail when folding (compile time) */
-  luaT_trybinTM(L, p1, p2, res, cast(TMS, op - LUA_OPADD + TM_ADD));
+  luaT_trybinTM(L, p1, p2, res, cast(TMS, (op - LUA_OPADD) + TM_ADD));
 }
 
 
 int luaO_hexavalue (int c) {
   if (lisdigit(c)) return c - '0';
-  else return ltolower(c) - 'a' + 10;
+  else return (ltolower(c) - 'a') + 10;
 }
 
 
@@ -172,10 +179,9 @@
 ** Lua's implementation for 'lua_strx2number'
 ** ===================================================================
 */
+
 #if !defined(lua_strx2number)
 
-#include <math.h>
-
 /* maximum number of significant digits to read (to avoid overflows
    even with single floats) */
 #define MAXSIGDIG	30
@@ -185,21 +191,22 @@
 ** C99 specification for 'strtod'
 */
 static lua_Number lua_strx2number (const char *s, char **endptr) {
+  int dot = lua_getlocaledecpoint();
   lua_Number r = 0.0;  /* result (accumulator) */
   int sigdig = 0;  /* number of significant digits */
   int nosigdig = 0;  /* number of non-significant digits */
   int e = 0;  /* exponent correction */
   int neg;  /* 1 if number is negative */
-  int dot = 0;  /* true after seen a dot */
+  int hasdot = 0;  /* true after seen a dot */
   *endptr = cast(char *, s);  /* nothing is valid yet */
   while (lisspace(cast_uchar(*s))) s++;  /* skip initial spaces */
   neg = isneg(&s);  /* check signal */
   if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X')))  /* check '0x' */
     return 0.0;  /* invalid format (no '0x') */
   for (s += 2; ; s++) {  /* skip '0x' and read numeral */
-    if (*s == '.') {
-      if (dot) break;  /* second dot? stop loop */
-      else dot = 1;
+    if (*s == dot) {
+      if (hasdot) break;  /* second dot? stop loop */
+      else hasdot = 1;
     }
     else if (lisxdigit(cast_uchar(*s))) {
       if (sigdig == 0 && *s == '0')  /* non-significant digit (zero)? */
@@ -207,7 +214,7 @@
       else if (++sigdig <= MAXSIGDIG)  /* can read it without overflow? */
           r = (r * cast_num(16.0)) + luaO_hexavalue(*s);
       else e++; /* too many digits; ignore, but still count for exponent */
-      if (dot) e--;  /* decimal digit? correct exponent */
+      if (hasdot) e--;  /* decimal digit? correct exponent */
     }
     else break;  /* neither a dot nor a digit */
   }
@@ -244,7 +251,7 @@
     *result = lua_strx2number(s, &endptr);
   else
     *result = lua_str2number(s, &endptr);
-  if (endptr == s) return 0;  /* nothing recognized */
+  if (endptr == s) return NULL;  /* nothing recognized */
   while (lisspace(cast_uchar(*endptr))) endptr++;
   return (*endptr == '\0' ? endptr : NULL);  /* OK if no trailing characters */
 }
@@ -290,7 +297,7 @@
   }
   else
     return 0;  /* conversion failed */
-  return (e - s + 1);  /* success; return string size */
+  return (e - s) + 1;  /* success; return string size */
 }
 
 
@@ -324,12 +331,12 @@
   size_t len;
   lua_assert(ttisnumber(obj));
   if (ttisinteger(obj))
-    len = lua_integer2str(buff, ivalue(obj));
+    len = lua_integer2str(buff, sizeof(buff), ivalue(obj));
   else {
-    len = lua_number2str(buff, fltvalue(obj));
+    len = lua_number2str(buff, sizeof(buff), fltvalue(obj));
 #if !defined(LUA_COMPAT_FLOATSTRING)
     if (buff[strspn(buff, "-0123456789")] == '\0') {  /* looks like an int? */
-      buff[len++] = '.';
+      buff[len++] = lua_getlocaledecpoint();
       buff[len++] = '0';  /* adds '.0' to result */
     }
 #endif
@@ -339,7 +346,8 @@
 
 
 static void pushstr (lua_State *L, const char *str, size_t l) {
-  setsvalue2s(L, L->top++, luaS_newlstr(L, str, l));
+  setsvalue2s(L, L->top, luaS_newlstr(L, str, l));
+  luaD_inctop(L);
 }
 
 
@@ -350,7 +358,6 @@
   for (;;) {
     const char *e = strchr(fmt, '%');
     if (e == NULL) break;
-    luaD_checkstack(L, 2);  /* fmt + item */
     pushstr(L, fmt, e - fmt);
     switch (*(e+1)) {
       case 's': {
@@ -368,23 +375,23 @@
         break;
       }
       case 'd': {
-        setivalue(L->top++, va_arg(argp, int));
-        luaO_tostring(L, L->top - 1);
-        break;
+        setivalue(L->top, va_arg(argp, int));
+        goto top2str;
       }
       case 'I': {
-        setivalue(L->top++, cast(lua_Integer, va_arg(argp, l_uacInt)));
-        luaO_tostring(L, L->top - 1);
-        break;
+        setivalue(L->top, cast(lua_Integer, va_arg(argp, l_uacInt)));
+        goto top2str;
       }
       case 'f': {
-        setfltvalue(L->top++, cast_num(va_arg(argp, l_uacNumber)));
+        setfltvalue(L->top, cast_num(va_arg(argp, l_uacNumber)));
+      top2str:
+        luaD_inctop(L);
         luaO_tostring(L, L->top - 1);
         break;
       }
       case 'p': {
         char buff[4*sizeof(void *) + 8]; /* should be enough space for a '%p' */
-        int l = sprintf(buff, "%p", va_arg(argp, void *));
+        int l = l_sprintf(buff, sizeof(buff), "%p", va_arg(argp, void *));
         pushstr(L, buff, l);
         break;
       }

=== modified file 'src/third_party/eris/lobject.h'
--- src/third_party/eris/lobject.h	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lobject.h	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 2.106 2015/01/05 13:52:37 roberto Exp $
+** $Id: lobject.h,v 2.116 2015/11/03 18:33:10 roberto Exp $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -19,8 +19,8 @@
 /*
 ** Extra tags for non-values
 */
-#define LUA_TPROTO	LUA_NUMTAGS
-#define LUA_TDEADKEY	(LUA_NUMTAGS+1)
+#define LUA_TPROTO	LUA_NUMTAGS		/* function prototypes */
+#define LUA_TDEADKEY	(LUA_NUMTAGS+1)		/* removed keys in tables */
 
 /*
 ** number of all possible tags (including LUA_TNONE but excluding DEADKEY)
@@ -35,8 +35,6 @@
 ** bit 6: whether value is collectable
 */
 
-#define VARBITS		(3 << 4)
-
 
 /*
 ** LUA_TFUNCTION variants:
@@ -90,22 +88,32 @@
 
 
 
-/*
-** Union of all Lua values
-*/
-typedef union Value Value;
-
-
-
 
 /*
 ** Tagged Values. This is the basic representation of values in Lua,
 ** an actual value plus a tag with its type.
 */
 
+/*
+** Union of all Lua values
+*/
+typedef union Value {
+  GCObject *gc;    /* collectable objects */
+  void *p;         /* light userdata */
+  int b;           /* booleans */
+  lua_CFunction f; /* light C functions */
+  lua_Integer i;   /* integer numbers */
+  lua_Number n;    /* float numbers */
+} Value;
+
+
 #define TValuefields	Value value_; int tt_
 
-typedef struct lua_TValue TValue;
+
+typedef struct lua_TValue {
+  TValuefields;
+} TValue;
+
 
 
 /* macro defining a nil value */
@@ -179,9 +187,9 @@
 /* Macros for internal tests */
 #define righttt(obj)		(ttype(obj) == gcvalue(obj)->tt)
 
-#define checkliveness(g,obj) \
+#define checkliveness(L,obj) \
 	lua_longassert(!iscollectable(obj) || \
-			(righttt(obj) && !isdead(g,gcvalue(obj))))
+		(righttt(obj) && (L == NULL || !isdead(G(L),gcvalue(obj)))))
 
 
 /* Macros to set values */
@@ -190,9 +198,15 @@
 #define setfltvalue(obj,x) \
   { TValue *io=(obj); val_(io).n=(x); settt_(io, LUA_TNUMFLT); }
 
+#define chgfltvalue(obj,x) \
+  { TValue *io=(obj); lua_assert(ttisfloat(io)); val_(io).n=(x); }
+
 #define setivalue(obj,x) \
   { TValue *io=(obj); val_(io).i=(x); settt_(io, LUA_TNUMINT); }
 
+#define chgivalue(obj,x) \
+  { TValue *io=(obj); lua_assert(ttisinteger(io)); val_(io).i=(x); }
+
 #define setnilvalue(obj) settt_(obj, LUA_TNIL)
 
 #define setfvalue(obj,x) \
@@ -211,32 +225,32 @@
 #define setsvalue(L,obj,x) \
   { TValue *io = (obj); TString *x_ = (x); \
     val_(io).gc = obj2gco(x_); settt_(io, ctb(x_->tt)); \
-    checkliveness(G(L),io); }
+    checkliveness(L,io); }
 
 #define setuvalue(L,obj,x) \
   { TValue *io = (obj); Udata *x_ = (x); \
     val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TUSERDATA)); \
-    checkliveness(G(L),io); }
+    checkliveness(L,io); }
 
 #define setthvalue(L,obj,x) \
   { TValue *io = (obj); lua_State *x_ = (x); \
     val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTHREAD)); \
-    checkliveness(G(L),io); }
+    checkliveness(L,io); }
 
 #define setclLvalue(L,obj,x) \
   { TValue *io = (obj); LClosure *x_ = (x); \
     val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TLCL)); \
-    checkliveness(G(L),io); }
+    checkliveness(L,io); }
 
 #define setclCvalue(L,obj,x) \
   { TValue *io = (obj); CClosure *x_ = (x); \
     val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TCCL)); \
-    checkliveness(G(L),io); }
+    checkliveness(L,io); }
 
 #define sethvalue(L,obj,x) \
   { TValue *io = (obj); Table *x_ = (x); \
     val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTABLE)); \
-    checkliveness(G(L),io); }
+    checkliveness(L,io); }
 
 #define setdeadvalue(obj)	settt_(obj, LUA_TDEADKEY)
 
@@ -244,7 +258,7 @@
 
 #define setobj(L,obj1,obj2) \
 	{ TValue *io1=(obj1); *io1 = *(obj2); \
-	  (void)L; checkliveness(G(L),io1); }
+	  (void)L; checkliveness(L,io1); }
 
 
 /*
@@ -260,12 +274,13 @@
 #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
 
+/* to table (define it as an expression to be used in macros) */
+#define setobj2t(L,o1,o2)  ((void)L, *(o1)=*(o2), checkliveness(L,(o1)))
+
 
 
 
@@ -276,21 +291,6 @@
 */
 
 
-union Value {
-  GCObject *gc;    /* collectable objects */
-  void *p;         /* light userdata */
-  int b;           /* booleans */
-  lua_CFunction f; /* light C functions */
-  lua_Integer i;   /* integer numbers */
-  lua_Number n;    /* float numbers */
-};
-
-
-struct lua_TValue {
-  TValuefields;
-};
-
-
 typedef TValue *StkId;  /* index to stack elements */
 
 
@@ -303,9 +303,12 @@
 typedef struct TString {
   CommonHeader;
   lu_byte extra;  /* reserved words for short strings; "has hash" for longs */
+  lu_byte shrlen;  /* length for short strings */
   unsigned int hash;
-  size_t len;  /* number of characters in string */
-  struct TString *hnext;  /* linked list for hash table */
+  union {
+    size_t lnglen;  /* length for long strings */
+    struct TString *hnext;  /* linked list for hash table */
+  } u;
 } TString;
 
 
@@ -322,13 +325,19 @@
 ** Get the actual string (array of bytes) from a 'TString'.
 ** (Access to 'extra' ensures that value is really a 'TString'.)
 */
-#define getaddrstr(ts)	(cast(char *, (ts)) + sizeof(UTString))
 #define getstr(ts)  \
-  check_exp(sizeof((ts)->extra), cast(const char*, getaddrstr(ts)))
+  check_exp(sizeof((ts)->extra), cast(char *, (ts)) + sizeof(UTString))
+
 
 /* get the actual string (array of bytes) from a Lua value */
 #define svalue(o)       getstr(tsvalue(o))
 
+/* get string length from 'TString *s' */
+#define tsslen(s)	((s)->tt == LUA_TSHRSTR ? (s)->shrlen : (s)->u.lnglen)
+
+/* get string length from 'TValue *o' */
+#define vslen(o)	tsslen(tsvalue(o))
+
 
 /*
 ** Header for userdata; memory area follows the end of this structure
@@ -361,14 +370,14 @@
 
 #define setuservalue(L,u,o) \
 	{ const TValue *io=(o); Udata *iu = (u); \
-	  iu->user_ = io->value_; iu->ttuv_ = io->tt_; \
-	  checkliveness(G(L),io); }
+	  iu->user_ = io->value_; iu->ttuv_ = rttype(io); \
+	  checkliveness(L,io); }
 
 
 #define getuservalue(L,u,o) \
 	{ TValue *io=(o); const Udata *iu = (u); \
-	  io->value_ = iu->user_; io->tt_ = iu->ttuv_; \
-	  checkliveness(G(L),io); }
+	  io->value_ = iu->user_; settt_(io, iu->ttuv_); \
+	  checkliveness(L,io); }
 
 
 /*
@@ -376,7 +385,7 @@
 */
 typedef struct Upvaldesc {
   TString *name;  /* upvalue name (for debug information) */
-  lu_byte instack;  /* whether it is in stack */
+  lu_byte instack;  /* whether it is in stack (register) */
   lu_byte idx;  /* index of upvalue (in stack or in outer function's list) */
 } Upvaldesc;
 
@@ -398,23 +407,23 @@
 typedef struct Proto {
   CommonHeader;
   lu_byte numparams;  /* number of fixed parameters */
-  lu_byte is_vararg;
-  lu_byte maxstacksize;  /* maximum stack used by this function */
+  lu_byte is_vararg;  /* 2: declared vararg; 1: uses vararg */
+  lu_byte maxstacksize;  /* number of registers needed by this function */
   int sizeupvalues;  /* size of 'upvalues' */
   int sizek;  /* size of 'k' */
   int sizecode;
   int sizelineinfo;
   int sizep;  /* size of 'p' */
   int sizelocvars;
-  int linedefined;
-  int lastlinedefined;
+  int linedefined;  /* debug information  */
+  int lastlinedefined;  /* debug information  */
   TValue *k;  /* constants used by the function */
-  Instruction *code;
+  Instruction *code;  /* opcodes */
   struct Proto **p;  /* functions defined inside the function */
   int *lineinfo;  /* map from opcodes to source lines (debug information) */
   LocVar *locvars;  /* information about local variables (debug information) */
   Upvaldesc *upvalues;  /* upvalue information */
-  struct LClosure *cache;  /* last created closure with this prototype */
+  struct LClosure *cache;  /* last-created closure with this prototype */
   TString  *source;  /* used for debug information */
   GCObject *gclist;
 } Proto;
@@ -476,7 +485,7 @@
 #define setnodekey(L,key,obj) \
 	{ TKey *k_=(key); const TValue *io_=(obj); \
 	  k_->nk.value_ = io_->value_; k_->nk.tt_ = io_->tt_; \
-	  (void)L; checkliveness(G(L),io_); }
+	  (void)L; checkliveness(L,io_); }
 
 
 typedef struct Node {

=== modified file 'src/third_party/eris/loslib.c'
--- src/third_party/eris/loslib.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/loslib.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: loslib.c,v 1.54 2014/12/26 14:46:07 roberto Exp $
+** $Id: loslib.c,v 1.60 2015/11/19 19:16:22 roberto Exp $
 ** Standard Operating System library
 ** See Copyright Notice in lua.h
 */
@@ -22,10 +22,12 @@
 #include "lualib.h"
 
 
+/*
+** {==================================================================
+** list of valid conversion specifiers for the 'strftime' function
+** ===================================================================
+*/
 #if !defined(LUA_STRFTIMEOPTIONS)	/* { */
-/*
-** list of valid conversion specifiers for the 'strftime' function
-*/
 
 #if defined(LUA_USE_C89)
 #define LUA_STRFTIMEOPTIONS	{ "aAbBcdHIjmMpSUwWxXyYz%", "" }
@@ -37,8 +39,14 @@
 #endif
 
 #endif					/* } */
-
-
+/* }================================================================== */
+
+
+/*
+** {==================================================================
+** Configuration for time-related stuff
+** ===================================================================
+*/
 
 #if !defined(l_time_t)		/* { */
 /*
@@ -46,17 +54,48 @@
 */
 #define l_timet			lua_Integer
 #define l_pushtime(L,t)		lua_pushinteger(L,(lua_Integer)(t))
-#define l_checktime(L,a)	((time_t)luaL_checkinteger(L,a))
-
-#endif				/* } */
-
-
-
+
+static time_t l_checktime (lua_State *L, int arg) {
+  lua_Integer t = luaL_checkinteger(L, arg);
+  luaL_argcheck(L, (time_t)t == t, arg, "time out-of-bounds");
+  return (time_t)t;
+}
+
+#endif				/* } */
+
+
+#if !defined(l_gmtime)		/* { */
+/*
+** By default, Lua uses gmtime/localtime, except when POSIX is available,
+** where it uses gmtime_r/localtime_r
+*/
+
+#if defined(LUA_USE_POSIX)	/* { */
+
+#define l_gmtime(t,r)		gmtime_r(t,r)
+#define l_localtime(t,r)	localtime_r(t,r)
+
+#else				/* }{ */
+
+/* ISO C definitions */
+#define l_gmtime(t,r)		((void)(r)->tm_sec, gmtime(t))
+#define l_localtime(t,r)  	((void)(r)->tm_sec, localtime(t))
+
+#endif				/* } */
+
+#endif				/* } */
+
+/* }================================================================== */
+
+
+/*
+** {==================================================================
+** Configuration for 'tmpnam':
+** By default, Lua uses tmpnam except when POSIX is available, where
+** it uses mkstemp.
+** ===================================================================
+*/
 #if !defined(lua_tmpnam)	/* { */
-/*
-** By default, Lua uses tmpnam except when POSIX is available, where it
-** uses mkstemp.
-*/
 
 #if defined(LUA_USE_POSIX)	/* { */
 
@@ -83,29 +122,8 @@
 #endif				/* } */
 
 #endif				/* } */
-
-
-
-#if !defined(l_gmtime)		/* { */
-/*
-** By default, Lua uses gmtime/localtime, except when POSIX is available,
-** where it uses gmtime_r/localtime_r
-*/
-
-#if defined(LUA_USE_POSIX)	/* { */
-
-#define l_gmtime(t,r)		gmtime_r(t,r)
-#define l_localtime(t,r)	localtime_r(t,r)
-
-#else				/* }{ */
-
-/* ISO C definitions */
-#define l_gmtime(t,r)		((void)(r)->tm_sec, gmtime(t))
-#define l_localtime(t,r)  	((void)(r)->tm_sec, localtime(t))
-
-#endif				/* } */
-
-#endif				/* } */
+/* }================================================================== */
+
 
 
 
@@ -185,17 +203,29 @@
 }
 
 
-static int getfield (lua_State *L, const char *key, int d) {
-  int res, isnum;
-  lua_getfield(L, -1, key);
-  res = (int)lua_tointegerx(L, -1, &isnum);
-  if (!isnum) {
-    if (d < 0)
+/* maximum value for date fields (to avoid arithmetic overflows with 'int') */
+#if !defined(L_MAXDATEFIELD)
+#define L_MAXDATEFIELD	(INT_MAX / 2)
+#endif
+
+static int getfield (lua_State *L, const char *key, int d, int delta) {
+  int isnum;
+  int t = lua_getfield(L, -1, key);
+  lua_Integer res = lua_tointegerx(L, -1, &isnum);
+  if (!isnum) {  /* field is not a number? */
+    if (t != LUA_TNIL)  /* some other value? */
+      return luaL_error(L, "field '%s' not an integer", key);
+    else if (d < 0)  /* absent field; no default? */
       return luaL_error(L, "field '%s' missing in date table", key);
     res = d;
   }
+  else {
+    if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD))
+      return luaL_error(L, "field '%s' out-of-bounds", key);
+    res -= delta;
+  }
   lua_pop(L, 1);
-  return res;
+  return (int)res;
 }
 
 
@@ -223,6 +253,10 @@
 }
 
 
+/* maximum size for an individual 'strftime' item */
+#define SIZETIMEFMT	250
+
+
 static int os_date (lua_State *L) {
   const char *s = luaL_optstring(L, 1, "%c");
   time_t t = luaL_opt(L, l_checktime, 2, time(NULL));
@@ -234,8 +268,8 @@
   else
     stm = l_localtime(&t, &tmr);
   if (stm == NULL)  /* invalid date? */
-    lua_pushnil(L);
-  else if (strcmp(s, "*t") == 0) {
+    luaL_error(L, "time result cannot be represented in this installation");
+  if (strcmp(s, "*t") == 0) {
     lua_createtable(L, 0, 9);  /* 9 = number of fields */
     setfield(L, "sec", stm->tm_sec);
     setfield(L, "min", stm->tm_min);
@@ -253,14 +287,14 @@
     cc[0] = '%';
     luaL_buffinit(L, &b);
     while (*s) {
-      if (*s != '%')  /* no conversion specifier? */
+      if (*s != '%')  /* not a conversion specifier? */
         luaL_addchar(&b, *s++);
       else {
         size_t reslen;
-        char buff[200];  /* should be big enough for any conversion result */
+        char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT);
         s = checkoption(L, s + 1, cc);
-        reslen = strftime(buff, sizeof(buff), cc, stm);
-        luaL_addlstring(&b, buff, reslen);
+        reslen = strftime(buff, SIZETIMEFMT, cc, stm);
+        luaL_addsize(&b, reslen);
       }
     }
     luaL_pushresult(&b);
@@ -277,28 +311,26 @@
     struct tm ts;
     luaL_checktype(L, 1, LUA_TTABLE);
     lua_settop(L, 1);  /* make sure table is at the top */
-    ts.tm_sec = getfield(L, "sec", 0);
-    ts.tm_min = getfield(L, "min", 0);
-    ts.tm_hour = getfield(L, "hour", 12);
-    ts.tm_mday = getfield(L, "day", -1);
-    ts.tm_mon = getfield(L, "month", -1) - 1;
-    ts.tm_year = getfield(L, "year", -1) - 1900;
+    ts.tm_sec = getfield(L, "sec", 0, 0);
+    ts.tm_min = getfield(L, "min", 0, 0);
+    ts.tm_hour = getfield(L, "hour", 12, 0);
+    ts.tm_mday = getfield(L, "day", -1, 0);
+    ts.tm_mon = getfield(L, "month", -1, 1);
+    ts.tm_year = getfield(L, "year", -1, 1900);
     ts.tm_isdst = getboolfield(L, "isdst");
     t = mktime(&ts);
   }
-  if (t != (time_t)(l_timet)t)
-    luaL_error(L, "time result cannot be represented in this Lua instalation");
-  else if (t == (time_t)(-1))
-    lua_pushnil(L);
-  else
-    l_pushtime(L, t);
+  if (t != (time_t)(l_timet)t || t == (time_t)(-1))
+    luaL_error(L, "time result cannot be represented in this installation");
+  l_pushtime(L, t);
   return 1;
 }
 
 
 static int os_difftime (lua_State *L) {
-  double res = difftime((l_checktime(L, 1)), (l_checktime(L, 2)));
-  lua_pushnumber(L, (lua_Number)res);
+  time_t t1 = l_checktime(L, 1);
+  time_t t2 = l_checktime(L, 2);
+  lua_pushnumber(L, (lua_Number)difftime(t1, t2));
   return 1;
 }
 

=== modified file 'src/third_party/eris/lparser.c'
--- src/third_party/eris/lparser.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lparser.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 2.147 2014/12/27 20:31:43 roberto Exp $
+** $Id: lparser.c,v 2.149 2015/11/02 16:09:30 roberto Exp $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */
@@ -760,7 +760,7 @@
         }
         case TK_DOTS: {  /* param -> '...' */
           luaX_next(ls);
-          f->is_vararg = 1;
+          f->is_vararg = 2;  /* declared vararg */
           break;
         }
         default: luaX_syntaxerror(ls, "<name> or '...' expected");
@@ -956,6 +956,7 @@
       FuncState *fs = ls->fs;
       check_condition(ls, fs->f->is_vararg,
                       "cannot use '...' outside a vararg function");
+      fs->f->is_vararg = 1;  /* function actually uses vararg */
       init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0));
       break;
     }
@@ -1610,7 +1611,7 @@
   BlockCnt bl;
   expdesc v;
   open_func(ls, fs, &bl);
-  fs->f->is_vararg = 1;  /* main function is always vararg */
+  fs->f->is_vararg = 2;  /* main function is always declared vararg */
   init_exp(&v, VLOCAL, 0);  /* create and... */
   newupvalue(fs, ls->envn, &v);  /* ...set environment upvalue */
   luaX_next(ls);  /* read first token */
@@ -1626,10 +1627,10 @@
   FuncState funcstate;
   LClosure *cl = luaF_newLclosure(L, 1);  /* create main closure */
   setclLvalue(L, L->top, cl);  /* anchor it (to avoid being collected) */
-  incr_top(L);
+  luaD_inctop(L);
   lexstate.h = luaH_new(L);  /* create table for scanner */
   sethvalue(L, L->top, lexstate.h);  /* anchor it */
-  incr_top(L);
+  luaD_inctop(L);
   funcstate.f = cl->p = luaF_newproto(L);
   funcstate.f->source = luaS_new(L, name);  /* create and anchor TString */
   lua_assert(iswhite(funcstate.f));  /* do not need barrier here */

=== modified file 'src/third_party/eris/lstate.c'
--- src/third_party/eris/lstate.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lstate.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.c,v 2.127 2014/11/02 19:33:33 roberto Exp $
+** $Id: lstate.c,v 2.133 2015/11/13 12:16:51 roberto Exp $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -37,9 +37,6 @@
 #endif
 
 
-#define MEMERRMSG	"not enough memory"
-
-
 /*
 ** a macro to help the creation of a unique random seed when a state is
 ** created; the seed is used to randomize hashes.
@@ -79,7 +76,7 @@
 */
 #define addbuff(b,p,e) \
   { size_t t = cast(size_t, e); \
-    memcpy(buff + p, &t, sizeof(t)); p += sizeof(t); }
+    memcpy(b + p, &t, sizeof(t)); p += sizeof(t); }
 
 static unsigned int makeseed (lua_State *L) {
   char buff[4 * sizeof(size_t)];
@@ -96,10 +93,14 @@
 
 /*
 ** set GCdebt to a new value keeping the value (totalbytes + GCdebt)
-** invariant
+** invariant (and avoiding underflows in 'totalbytes')
 */
 void luaE_setdebt (global_State *g, l_mem debt) {
-  g->totalbytes -= (debt - g->GCdebt);
+  l_mem tb = gettotalbytes(g);
+  lua_assert(tb > 0);
+  if (debt < tb - MAX_LMEM)
+    debt = tb - MAX_LMEM;  /* will make 'totalbytes == MAX_LMEM' */
+  g->totalbytes = tb - debt;
   g->GCdebt = debt;
 }
 
@@ -110,6 +111,7 @@
   L->ci->next = ci;
   ci->previous = L->ci;
   ci->next = NULL;
+  L->nci++;
   return ci;
 }
 
@@ -124,6 +126,7 @@
   while ((ci = next) != NULL) {
     next = ci->next;
     luaM_free(L, ci);
+    L->nci--;
   }
 }
 
@@ -133,13 +136,14 @@
 */
 void luaE_shrinkCI (lua_State *L) {
   CallInfo *ci = L->ci;
-  while (ci->next != NULL) {  /* while there is 'next' */
-    CallInfo *next2 = ci->next->next;  /* next's next */
-    if (next2 == NULL) break;
-    luaM_free(L, ci->next);  /* remove next */
+  CallInfo *next2;  /* next's next */
+  /* while there are two nexts */
+  while (ci->next != NULL && (next2 = ci->next->next) != NULL) {
+    luaM_free(L, ci->next);  /* free next */
+    L->nci--;
     ci->next = next2;  /* remove 'next' from the list */
     next2->previous = ci;
-    ci = next2;
+    ci = next2;  /* keep next's next */
   }
 }
 
@@ -169,6 +173,7 @@
     return;  /* stack not completely built yet */
   L->ci = &L->base_ci;  /* free the entire 'ci' list */
   luaE_freeCI(L);
+  lua_assert(L->nci == 0);
   luaM_freearray(L, L->stack, L->stacksize);  /* free stack array */
 }
 
@@ -200,12 +205,9 @@
   UNUSED(ud);
   stack_init(L, L);  /* init stack */
   init_registry(L, g);
-  luaS_resize(L, MINSTRTABSIZE);  /* initial size of string table */
+  luaS_init(L);
   luaT_init(L);
   luaX_init(L);
-  /* pre-create memory-error message */
-  g->memerrmsg = luaS_newliteral(L, MEMERRMSG);
-  luaC_fix(L, obj2gco(g->memerrmsg));  /* it should never be collected */
   g->gcrunning = 1;  /* allow gc */
   g->version = lua_version(NULL);
   luai_userstateopen(L);
@@ -220,6 +222,7 @@
   G(L) = g;
   L->stack = NULL;
   L->ci = NULL;
+  L->nci = 0;
   L->stacksize = 0;
   L->twups = L;  /* thread has no upvalues */
   L->errorJmp = NULL;
@@ -243,7 +246,6 @@
   if (g->version)  /* closing a fully built state? */
     luai_userstateclose(L);
   luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size);
-  luaZ_freebuffer(L, &g->buff);
   freestack(L);
   lua_assert(gettotalbytes(g) == sizeof(LG));
   (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0);  /* free main block */
@@ -312,7 +314,6 @@
   g->strt.size = g->strt.nuse = 0;
   g->strt.hash = NULL;
   setnilvalue(&g->l_registry);
-  luaZ_initbuffer(L, &g->buff);
   g->panic = NULL;
   g->version = NULL;
   g->gcstate = GCSpause;

=== modified file 'src/third_party/eris/lstate.h'
--- src/third_party/eris/lstate.h	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lstate.h	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 2.119 2014/10/30 18:53:28 roberto Exp $
+** $Id: lstate.h,v 2.128 2015/11/13 12:16:51 roberto Exp $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -89,11 +89,12 @@
 #define CIST_OAH	(1<<0)	/* original value of 'allowhook' */
 #define CIST_LUA	(1<<1)	/* call is running a Lua function */
 #define CIST_HOOKED	(1<<2)	/* call is running a debug hook */
-#define CIST_REENTRY	(1<<3)	/* call is running on same invocation of
-                                   luaV_execute of previous call */
+#define CIST_FRESH	(1<<3)	/* call is running on a fresh invocation
+                                   of luaV_execute */
 #define CIST_YPCALL	(1<<4)	/* call is a yieldable protected call */
 #define CIST_TAIL	(1<<5)	/* call was tail called */
 #define CIST_HOOKYIELD	(1<<6)	/* last hook called yielded */
+#define CIST_LEQ	(1<<7)  /* using __lt for __le */
 
 #define isLua(ci)	((ci)->callstatus & CIST_LUA)
 
@@ -108,7 +109,7 @@
 typedef struct global_State {
   lua_Alloc frealloc;  /* function to reallocate memory */
   void *ud;         /* auxiliary data to 'frealloc' */
-  lu_mem totalbytes;  /* number of bytes currently allocated - GCdebt */
+  l_mem totalbytes;  /* number of bytes currently allocated - GCdebt */
   l_mem GCdebt;  /* bytes allocated not yet compensated by the collector */
   lu_mem GCmemtrav;  /* memory traversed by the GC */
   lu_mem GCestimate;  /* an estimate of the non-garbage memory in use */
@@ -130,7 +131,6 @@
   GCObject *tobefnz;  /* list of userdata to be GC */
   GCObject *fixedgc;  /* list of objects not to be collected */
   struct lua_State *twups;  /* list of threads with open upvalues */
-  Mbuffer buff;  /* temporary buffer for string concatenation */
   unsigned int gcfinnum;  /* number of finalizers to call in each GC step */
   int gcpause;  /* size of pause between successive GCs */
   int gcstepmul;  /* GC 'granularity' */
@@ -140,6 +140,7 @@
   TString *memerrmsg;  /* memory-error message */
   TString *tmname[TM_N];  /* array with tag-method names */
   struct Table *mt[LUA_NUMTAGS];  /* metatables for basic types */
+  TString *strcache[STRCACHE_N][STRCACHE_M];  /* cache for strings in API */
 } global_State;
 
 
@@ -148,6 +149,7 @@
 */
 struct lua_State {
   CommonHeader;
+  unsigned short nci;  /* number of items in 'ci' list */
   lu_byte status;
   StkId top;  /* first free slot in the stack */
   global_State *l_G;
@@ -210,7 +212,7 @@
 
 
 /* actual number of total bytes allocated */
-#define gettotalbytes(g)	((g)->totalbytes + (g)->GCdebt)
+#define gettotalbytes(g)	cast(lu_mem, (g)->totalbytes + (g)->GCdebt)
 
 LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt);
 LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);

=== modified file 'src/third_party/eris/lstring.c'
--- src/third_party/eris/lstring.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lstring.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.c,v 2.45 2014/11/02 19:19:04 roberto Exp $
+** $Id: lstring.c,v 2.56 2015/11/23 11:32:51 roberto Exp $
 ** String table (keeps all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
@@ -22,6 +22,8 @@
 #include "lstring.h"
 
 
+#define MEMERRMSG       "not enough memory"
+
 
 /*
 ** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to
@@ -36,24 +38,33 @@
 ** equality for long strings
 */
 int luaS_eqlngstr (TString *a, TString *b) {
-  size_t len = a->len;
+  size_t len = a->u.lnglen;
   lua_assert(a->tt == LUA_TLNGSTR && b->tt == LUA_TLNGSTR);
   return (a == b) ||  /* same instance or... */
-    ((len == b->len) &&  /* equal length and ... */
+    ((len == b->u.lnglen) &&  /* equal length and ... */
      (memcmp(getstr(a), getstr(b), len) == 0));  /* equal contents */
 }
 
 
 unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) {
   unsigned int h = seed ^ cast(unsigned int, l);
-  size_t l1;
   size_t step = (l >> LUAI_HASHLIMIT) + 1;
-  for (l1 = l; l1 >= step; l1 -= step)
-    h = h ^ ((h<<5) + (h>>2) + cast_byte(str[l1 - 1]));
+  for (; l >= step; l -= step)
+    h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1]));
   return h;
 }
 
 
+unsigned int luaS_hashlongstr (TString *ts) {
+  lua_assert(ts->tt == LUA_TLNGSTR);
+  if (ts->extra == 0) {  /* no hash? */
+    ts->hash = luaS_hash(getstr(ts), ts->u.lnglen, ts->hash);
+    ts->extra = 1;  /* now it has its hash */
+  }
+  return ts->hash;
+}
+
+
 /*
 ** resizes the string table
 */
@@ -69,9 +80,9 @@
     TString *p = tb->hash[i];
     tb->hash[i] = NULL;
     while (p) {  /* for each node in the list */
-      TString *hnext = p->hnext;  /* save next */
+      TString *hnext = p->u.hnext;  /* save next */
       unsigned int h = lmod(p->hash, newsize);  /* new position */
-      p->hnext = tb->hash[h];  /* chain it */
+      p->u.hnext = tb->hash[h];  /* chain it */
       tb->hash[h] = p;
       p = hnext;
     }
@@ -85,23 +96,57 @@
 }
 
 
+/*
+** Clear API string cache. (Entries cannot be empty, so fill them with
+** a non-collectable string.)
+*/
+void luaS_clearcache (global_State *g) {
+  int i, j;
+  for (i = 0; i < STRCACHE_N; i++)
+    for (j = 0; j < STRCACHE_M; j++) {
+    if (iswhite(g->strcache[i][j]))  /* will entry be collected? */
+      g->strcache[i][j] = g->memerrmsg;  /* replace it with something fixed */
+    }
+}
+
+
+/*
+** Initialize the string table and the string cache
+*/
+void luaS_init (lua_State *L) {
+  global_State *g = G(L);
+  int i, j;
+  luaS_resize(L, MINSTRTABSIZE);  /* initial size of string table */
+  /* pre-create memory-error message */
+  g->memerrmsg = luaS_newliteral(L, MEMERRMSG);
+  luaC_fix(L, obj2gco(g->memerrmsg));  /* it should never be collected */
+  for (i = 0; i < STRCACHE_N; i++)  /* fill cache with valid strings */
+    for (j = 0; j < STRCACHE_M; j++)
+      g->strcache[i][j] = g->memerrmsg;
+}
+
+
 
 /*
 ** creates a new string object
 */
-static TString *createstrobj (lua_State *L, const char *str, size_t l,
-                              int tag, unsigned int h) {
+static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) {
   TString *ts;
   GCObject *o;
   size_t totalsize;  /* total size of TString object */
   totalsize = sizelstring(l);
   o = luaC_newobj(L, tag, totalsize);
   ts = gco2ts(o);
-  ts->len = l;
   ts->hash = h;
   ts->extra = 0;
-  memcpy(getaddrstr(ts), str, l * sizeof(char));
-  getaddrstr(ts)[l] = '\0';  /* ending 0 */
+  getstr(ts)[l] = '\0';  /* ending 0 */
+  return ts;
+}
+
+
+TString *luaS_createlngstrobj (lua_State *L, size_t l) {
+  TString *ts = createstrobj(L, l, LUA_TLNGSTR, G(L)->seed);
+  ts->u.lnglen = l;
   return ts;
 }
 
@@ -110,8 +155,8 @@
   stringtable *tb = &G(L)->strt;
   TString **p = &tb->hash[lmod(ts->hash, tb->size)];
   while (*p != ts)  /* find previous element */
-    p = &(*p)->hnext;
-  *p = (*p)->hnext;  /* remove element from its list */
+    p = &(*p)->u.hnext;
+  *p = (*p)->u.hnext;  /* remove element from its list */
   tb->nuse--;
 }
 
@@ -124,8 +169,9 @@
   global_State *g = G(L);
   unsigned int h = luaS_hash(str, l, g->seed);
   TString **list = &g->strt.hash[lmod(h, g->strt.size)];
-  for (ts = *list; ts != NULL; ts = ts->hnext) {
-    if (l == ts->len &&
+  lua_assert(str != NULL);  /* otherwise 'memcmp'/'memcpy' are undefined */
+  for (ts = *list; ts != NULL; ts = ts->u.hnext) {
+    if (l == ts->shrlen &&
         (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) {
       /* found! */
       if (isdead(g, ts))  /* dead (but not collected yet)? */
@@ -137,8 +183,10 @@
     luaS_resize(L, g->strt.size * 2);
     list = &g->strt.hash[lmod(h, g->strt.size)];  /* recompute with new size */
   }
-  ts = createstrobj(L, str, l, LUA_TSHRSTR, h);
-  ts->hnext = *list;
+  ts = createstrobj(L, l, LUA_TSHRSTR, h);
+  memcpy(getstr(ts), str, l * sizeof(char));
+  ts->shrlen = cast_byte(l);
+  ts->u.hnext = *list;
   *list = ts;
   g->strt.nuse++;
   return ts;
@@ -152,18 +200,36 @@
   if (l <= LUAI_MAXSHORTLEN)  /* short string? */
     return internshrstr(L, str, l);
   else {
-    if (l + 1 > (MAX_SIZE - sizeof(TString))/sizeof(char))
+    TString *ts;
+    if (l >= (MAX_SIZE - sizeof(TString))/sizeof(char))
       luaM_toobig(L);
-    return createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed);
+    ts = luaS_createlngstrobj(L, l);
+    memcpy(getstr(ts), str, l * sizeof(char));
+    return ts;
   }
 }
 
 
 /*
-** new zero-terminated string
+** Create or reuse a zero-terminated string, first checking in the
+** cache (using the string address as a key). The cache can contain
+** only zero-terminated strings, so it is safe to use 'strcmp' to
+** check hits.
 */
 TString *luaS_new (lua_State *L, const char *str) {
-  return luaS_newlstr(L, str, strlen(str));
+  unsigned int i = point2uint(str) % STRCACHE_N;  /* hash */
+  int j;
+  TString **p = G(L)->strcache[i];
+  for (j = 0; j < STRCACHE_M; j++) {
+    if (strcmp(str, getstr(p[j])) == 0)  /* hit? */
+      return p[j];  /* that is it */
+  }
+  /* normal route */
+  for (j = STRCACHE_M - 1; j > 0; j--)
+    p[j] = p[j - 1];  /* move out last element */
+  /* new element is first in the list */
+  p[0] = luaS_newlstr(L, str, strlen(str));
+  return p[0];
 }
 
 

=== modified file 'src/third_party/eris/lstring.h'
--- src/third_party/eris/lstring.h	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lstring.h	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.h,v 1.56 2014/07/18 14:46:47 roberto Exp $
+** $Id: lstring.h,v 1.61 2015/11/03 15:36:01 roberto Exp $
 ** String table (keep all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
@@ -13,7 +13,6 @@
 
 
 #define sizelstring(l)  (sizeof(union UTString) + ((l) + 1) * sizeof(char))
-#define sizestring(s)	sizelstring((s)->len)
 
 #define sizeludata(l)	(sizeof(union UUdata) + (l))
 #define sizeudata(u)	sizeludata((u)->len)
@@ -35,12 +34,16 @@
 
 
 LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed);
+LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts);
 LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b);
 LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
+LUAI_FUNC void luaS_clearcache (global_State *g);
+LUAI_FUNC void luaS_init (lua_State *L);
 LUAI_FUNC void luaS_remove (lua_State *L, TString *ts);
 LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s);
 LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
 LUAI_FUNC TString *luaS_new (lua_State *L, const char *str);
+LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l);
 
 
 #endif

=== modified file 'src/third_party/eris/lstrlib.c'
--- src/third_party/eris/lstrlib.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lstrlib.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lstrlib.c,v 1.221 2014/12/11 14:03:07 roberto Exp $
+** $Id: lstrlib.c,v 1.239 2015/11/25 16:28:17 roberto Exp $
 ** Standard library for string operations and pattern-matching
 ** See Copyright Notice in lua.h
 */
@@ -11,6 +11,7 @@
 
 
 #include <ctype.h>
+#include <float.h>
 #include <limits.h>
 #include <stddef.h>
 #include <stdio.h>
@@ -40,8 +41,10 @@
 ** Some sizes are better limited to fit in 'int', but must also fit in
 ** 'size_t'. (We assume that 'lua_Integer' cannot be smaller than 'int'.)
 */
+#define MAX_SIZET	((size_t)(~(size_t)0))
+
 #define MAXSIZE  \
-	(sizeof(size_t) < sizeof(int) ? (~(size_t)0) : (size_t)(INT_MAX))
+	(sizeof(size_t) < sizeof(int) ? MAX_SIZET : (size_t)(INT_MAX))
 
 
 
@@ -70,7 +73,7 @@
   if (start < 1) start = 1;
   if (end > (lua_Integer)l) end = l;
   if (start <= end)
-    lua_pushlstring(L, s + start - 1, (size_t)(end - start + 1));
+    lua_pushlstring(L, s + start - 1, (size_t)(end - start) + 1);
   else lua_pushliteral(L, "");
   return 1;
 }
@@ -149,9 +152,9 @@
   if (posi < 1) posi = 1;
   if (pose > (lua_Integer)l) pose = l;
   if (posi > pose) return 0;  /* empty interval; return no values */
-  n = (int)(pose -  posi + 1);
-  if (posi + n <= pose)  /* arithmetic overflow? */
+  if (pose - posi >= INT_MAX)  /* arithmetic overflow? */
     return luaL_error(L, "string slice too long");
+  n = (int)(pose -  posi) + 1;
   luaL_checkstack(L, n, "string slice too long");
   for (i=0; i<n; i++)
     lua_pushinteger(L, uchar(s[posi+i-1]));
@@ -207,11 +210,12 @@
 
 
 typedef struct MatchState {
-  int matchdepth;  /* control for recursive depth (to avoid C stack overflow) */
   const char *src_init;  /* init of source string */
   const char *src_end;  /* end ('\0') of source string */
   const char *p_end;  /* end ('\0') of pattern */
   lua_State *L;
+  size_t nrep;  /* limit to avoid non-linear complexity */
+  int matchdepth;  /* control for recursive depth (to avoid C stack overflow) */
   int level;  /* total number of captures (finished or unfinished) */
   struct {
     const char *init;
@@ -230,6 +234,17 @@
 #endif
 
 
+/*
+** parameters to control the maximum number of operators handled in
+** a match (to avoid non-linear complexity). The maximum will be:
+** (subject length) * A_REPS + B_REPS
+*/
+#if !defined(A_REPS)
+#define A_REPS		4
+#define B_REPS		100000
+#endif
+
+
 #define L_ESC		'%'
 #define SPECIALS	"^$*+?.([%-"
 
@@ -487,6 +502,8 @@
             s = NULL;  /* fail */
         }
         else {  /* matched once */
+          if (ms->nrep-- == 0)
+            luaL_error(ms->L, "pattern too complex");
           switch (*ep) {  /* handle optional suffix */
             case '?': {  /* optional */
               const char *res;
@@ -499,7 +516,7 @@
             }
             case '+':  /* 1 or more repetitions */
               s++;  /* 1 match already done */
-              /* go through */
+              /* FALLTHROUGH */
             case '*':  /* 0 or more repetitions */
               s = max_expand(ms, s, p, ep);
               break;
@@ -554,7 +571,7 @@
     ptrdiff_t l = ms->capture[i].len;
     if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");
     if (l == CAP_POSITION)
-      lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1);
+      lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1);
     else
       lua_pushlstring(ms->L, ms->capture[i].init, l);
   }
@@ -583,6 +600,26 @@
 }
 
 
+static void prepstate (MatchState *ms, lua_State *L,
+                       const char *s, size_t ls, const char *p, size_t lp) {
+  ms->L = L;
+  ms->matchdepth = MAXCCALLS;
+  ms->src_init = s;
+  ms->src_end = s + ls;
+  ms->p_end = p + lp;
+  if (ls < (MAX_SIZET - B_REPS) / A_REPS)
+    ms->nrep = A_REPS * ls + B_REPS;
+  else  /* overflow (very long subject) */
+    ms->nrep = MAX_SIZET;  /* no limit */
+}
+
+
+static void reprepstate (MatchState *ms) {
+  ms->level = 0;
+  lua_assert(ms->matchdepth == MAXCCALLS);
+}
+
+
 static int str_find_aux (lua_State *L, int find) {
   size_t ls, lp;
   const char *s = luaL_checklstring(L, 1, &ls);
@@ -598,8 +635,8 @@
     /* do a plain search */
     const char *s2 = lmemfind(s + init - 1, ls - (size_t)init + 1, p, lp);
     if (s2) {
-      lua_pushinteger(L, s2 - s + 1);
-      lua_pushinteger(L, s2 - s + lp);
+      lua_pushinteger(L, (s2 - s) + 1);
+      lua_pushinteger(L, (s2 - s) + lp);
       return 2;
     }
   }
@@ -610,18 +647,13 @@
     if (anchor) {
       p++; lp--;  /* skip anchor character */
     }
-    ms.L = L;
-    ms.matchdepth = MAXCCALLS;
-    ms.src_init = s;
-    ms.src_end = s + ls;
-    ms.p_end = p + lp;
+    prepstate(&ms, L, s, ls, p, lp);
     do {
       const char *res;
-      ms.level = 0;
-      lua_assert(ms.matchdepth == MAXCCALLS);
+      reprepstate(&ms);
       if ((res=match(&ms, s1, p)) != NULL) {
         if (find) {
-          lua_pushinteger(L, s1 - s + 1);  /* start */
+          lua_pushinteger(L, (s1 - s) + 1);  /* start */
           lua_pushinteger(L, res - s);   /* end */
           return push_captures(&ms, NULL, 0) + 2;
         }
@@ -645,29 +677,26 @@
 }
 
 
+/* state for 'gmatch' */
+typedef struct GMatchState {
+  const char *src;  /* current position */
+  const char *p;  /* pattern */
+  MatchState ms;  /* match state */
+} GMatchState;
+
+
 static int gmatch_aux (lua_State *L) {
-  MatchState ms;
-  size_t ls, lp;
-  const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
-  const char *p = lua_tolstring(L, lua_upvalueindex(2), &lp);
+  GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3));
   const char *src;
-  ms.L = L;
-  ms.matchdepth = MAXCCALLS;
-  ms.src_init = s;
-  ms.src_end = s+ls;
-  ms.p_end = p + lp;
-  for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3));
-       src <= ms.src_end;
-       src++) {
+  for (src = gm->src; src <= gm->ms.src_end; src++) {
     const char *e;
-    ms.level = 0;
-    lua_assert(ms.matchdepth == MAXCCALLS);
-    if ((e = match(&ms, src, p)) != NULL) {
-      lua_Integer newstart = e-s;
-      if (e == src) newstart++;  /* empty match? go at least one position */
-      lua_pushinteger(L, newstart);
-      lua_replace(L, lua_upvalueindex(3));
-      return push_captures(&ms, src, e);
+    reprepstate(&gm->ms);
+    if ((e = match(&gm->ms, src, gm->p)) != NULL) {
+      if (e == src)  /* empty match? */
+        gm->src =src + 1;  /* go at least one position */
+      else
+        gm->src = e;
+      return push_captures(&gm->ms, src, e);
     }
   }
   return 0;  /* not found */
@@ -675,10 +704,14 @@
 
 
 static int gmatch (lua_State *L) {
-  luaL_checkstring(L, 1);
-  luaL_checkstring(L, 2);
-  lua_settop(L, 2);
-  lua_pushinteger(L, 0);
+  size_t ls, lp;
+  const char *s = luaL_checklstring(L, 1, &ls);
+  const char *p = luaL_checklstring(L, 2, &lp);
+  GMatchState *gm;
+  lua_settop(L, 2);  /* keep them on closure to avoid being collected */
+  gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState));
+  prepstate(&gm->ms, L, s, ls, p, lp);
+  gm->src = s; gm->p = p;
   lua_pushcclosure(L, gmatch_aux, 3);
   return 1;
 }
@@ -760,17 +793,11 @@
   if (anchor) {
     p++; lp--;  /* skip anchor character */
   }
-  ms.L = L;
-  ms.matchdepth = MAXCCALLS;
-  ms.src_init = src;
-  ms.src_end = src+srcl;
-  ms.p_end = p + lp;
+  prepstate(&ms, L, src, srcl, p, lp);
   while (n < max_s) {
     const char *e;
-    ms.level = 0;
-    lua_assert(ms.matchdepth == MAXCCALLS);
-    e = match(&ms, src, p);
-    if (e) {
+    reprepstate(&ms);
+    if ((e = match(&ms, src, p)) != NULL) {
       n++;
       add_value(&ms, &b, src, e, tr);
     }
@@ -797,17 +824,102 @@
 ** =======================================================
 */
 
-/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
-#define MAX_ITEM	512
+#if !defined(lua_number2strx)	/* { */
+
+/*
+** Hexadecimal floating-point formatter
+*/
+
+#include <locale.h>
+#include <math.h>
+
+#define SIZELENMOD	(sizeof(LUA_NUMBER_FRMLEN)/sizeof(char))
+
+
+/*
+** Number of bits that goes into the first digit. It can be any value
+** between 1 and 4; the following definition tries to align the number
+** to nibble boundaries by making what is left after that first digit a
+** multiple of 4.
+*/
+#define L_NBFD		((l_mathlim(MANT_DIG) - 1)%4 + 1)
+
+
+/*
+** Add integer part of 'x' to buffer and return new 'x'
+*/
+static lua_Number adddigit (char *buff, int n, lua_Number x) {
+  lua_Number dd = l_mathop(floor)(x);  /* get integer part from 'x' */
+  int d = (int)dd;
+  buff[n] = (d < 10 ? d + '0' : d - 10 + 'a');  /* add to buffer */
+  return x - dd;  /* return what is left */
+}
+
+
+static int num2straux (char *buff, int sz, lua_Number x) {
+  if (x != x || x == HUGE_VAL || x == -HUGE_VAL)  /* inf or NaN? */
+    return l_sprintf(buff, sz, LUA_NUMBER_FMT, x);  /* equal to '%g' */
+  else if (x == 0) {  /* can be -0... */
+    /* create "0" or "-0" followed by exponent */
+    return l_sprintf(buff, sz, LUA_NUMBER_FMT "x0p+0", x);
+  }
+  else {
+    int e;
+    lua_Number m = l_mathop(frexp)(x, &e);  /* 'x' fraction and exponent */
+    int n = 0;  /* character count */
+    if (m < 0) {  /* is number negative? */
+      buff[n++] = '-';  /* add signal */
+      m = -m;  /* make it positive */
+    }
+    buff[n++] = '0'; buff[n++] = 'x';  /* add "0x" */
+    m = adddigit(buff, n++, m * (1 << L_NBFD));  /* add first digit */
+    e -= L_NBFD;  /* this digit goes before the radix point */
+    if (m > 0) {  /* more digits? */
+      buff[n++] = lua_getlocaledecpoint();  /* add radix point */
+      do {  /* add as many digits as needed */
+        m = adddigit(buff, n++, m * 16);
+      } while (m > 0);
+    }
+    n += l_sprintf(buff + n, sz - n, "p%+d", e);  /* add exponent */
+    lua_assert(n < sz);
+    return n;
+  }
+}
+
+
+static int lua_number2strx (lua_State *L, char *buff, int sz,
+                            const char *fmt, lua_Number x) {
+  int n = num2straux(buff, sz, x);
+  if (fmt[SIZELENMOD] == 'A') {
+    int i;
+    for (i = 0; i < n; i++)
+      buff[i] = toupper(uchar(buff[i]));
+  }
+  else if (fmt[SIZELENMOD] != 'a')
+    luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented");
+  return n;
+}
+
+#endif				/* } */
+
+
+/*
+** Maximum size of each formatted item. This maximum size is produced
+** by format('%.99f', -maxfloat), and is equal to 99 + 3 ('-', '.',
+** and '\0') + number of decimal digits to represent maxfloat (which
+** is maximum exponent + 1). (99+3+1 then rounded to 120 for "extra
+** expenses", such as locale-dependent stuff)
+*/
+#define MAX_ITEM        (120 + l_mathlim(MAX_10_EXP))
+
 
 /* valid flags in a format specification */
 #define FLAGS	"-+ #0"
 
 /*
 ** maximum size of each format specification (such as "%-099.99d")
-** (+2 for length modifiers; +10 accounts for %99.99x plus margin of error)
 */
-#define MAX_FORMAT	(sizeof(FLAGS) + 2 + 10)
+#define MAX_FORMAT	32
 
 
 static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
@@ -822,9 +934,9 @@
     else if (*s == '\0' || iscntrl(uchar(*s))) {
       char buff[10];
       if (!isdigit(uchar(*(s+1))))
-        sprintf(buff, "\\%d", (int)uchar(*s));
+        l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s));
       else
-        sprintf(buff, "\\%03d", (int)uchar(*s));
+        l_sprintf(buff, sizeof(buff), "\\%03d", (int)uchar(*s));
       luaL_addstring(b, buff);
     }
     else
@@ -849,8 +961,8 @@
   if (isdigit(uchar(*p)))
     luaL_error(L, "invalid format (width or precision too long)");
   *(form++) = '%';
-  memcpy(form, strfrmt, (p - strfrmt + 1) * sizeof(char));
-  form += p - strfrmt + 1;
+  memcpy(form, strfrmt, ((p - strfrmt) + 1) * sizeof(char));
+  form += (p - strfrmt) + 1;
   *form = '\0';
   return p;
 }
@@ -891,23 +1003,25 @@
       strfrmt = scanformat(L, strfrmt, form);
       switch (*strfrmt++) {
         case 'c': {
-          nb = sprintf(buff, form, (int)luaL_checkinteger(L, arg));
+          nb = l_sprintf(buff, MAX_ITEM, form, (int)luaL_checkinteger(L, arg));
           break;
         }
         case 'd': case 'i':
         case 'o': case 'u': case 'x': case 'X': {
           lua_Integer n = luaL_checkinteger(L, arg);
           addlenmod(form, LUA_INTEGER_FRMLEN);
-          nb = sprintf(buff, form, n);
+          nb = l_sprintf(buff, MAX_ITEM, form, n);
           break;
         }
-#if defined(LUA_USE_AFORMAT)
         case 'a': case 'A':
-#endif
+          addlenmod(form, LUA_NUMBER_FRMLEN);
+          nb = lua_number2strx(L, buff, MAX_ITEM, form,
+                                  luaL_checknumber(L, arg));
+          break;
         case 'e': case 'E': case 'f':
         case 'g': case 'G': {
           addlenmod(form, LUA_NUMBER_FRMLEN);
-          nb = sprintf(buff, form, luaL_checknumber(L, arg));
+          nb = l_sprintf(buff, MAX_ITEM, form, luaL_checknumber(L, arg));
           break;
         }
         case 'q': {
@@ -917,23 +1031,27 @@
         case 's': {
           size_t l;
           const char *s = luaL_tolstring(L, arg, &l);
-          if (!strchr(form, '.') && l >= 100) {
-            /* no precision and string is too long to be formatted;
-               keep original string */
-            luaL_addvalue(&b);
-            break;
-          }
+          if (form[2] == '\0')  /* no modifiers? */
+            luaL_addvalue(&b);  /* keep entire string */
           else {
-            nb = sprintf(buff, form, s);
-            lua_pop(L, 1);  /* remove result from 'luaL_tolstring' */
-            break;
+            luaL_argcheck(L, l == strlen(s), arg, "string contains zeros");
+            if (!strchr(form, '.') && l >= 100) {
+              /* no precision and string is too long to be formatted */
+              luaL_addvalue(&b);  /* keep entire string */
+            }
+            else {  /* format the string into 'buff' */
+              nb = l_sprintf(buff, MAX_ITEM, form, s);
+              lua_pop(L, 1);  /* remove result from 'luaL_tolstring' */
+            }
           }
+          break;
         }
         default: {  /* also treat cases 'pnLlh' */
           return luaL_error(L, "invalid option '%%%c' to 'format'",
                                *(strfrmt - 1));
         }
       }
+      lua_assert(nb < MAX_ITEM);
       luaL_addsize(&b, nb);
     }
   }
@@ -1225,8 +1343,13 @@
       case Kchar: {  /* fixed-size string */
         size_t len;
         const char *s = luaL_checklstring(L, arg, &len);
-        luaL_argcheck(L, len == (size_t)size, arg, "wrong length");
-        luaL_addlstring(&b, s, size);
+        if ((size_t)size <= len)  /* string larger than (or equal to) needed? */
+          luaL_addlstring(&b, s, size);  /* truncate string to asked size */
+        else {  /* string smaller than needed */
+          luaL_addlstring(&b, s, len);  /* add it all */
+          while (len++ < (size_t)size)  /* pad extra space */
+            luaL_addchar(&b, LUA_PACKPADBYTE);
+        }
         break;
       }
       case Kstring: {  /* strings with length count */
@@ -1249,7 +1372,7 @@
         totalsize += len + 1;
         break;
       }
-      case Kpadding: luaL_addchar(&b, LUA_PACKPADBYTE);  /* go through */
+      case Kpadding: luaL_addchar(&b, LUA_PACKPADBYTE);  /* FALLTHROUGH */
       case Kpaddalign: case Knop:
         arg--;  /* undo increment */
         break;
@@ -1276,7 +1399,7 @@
       case Kstring:  /* strings with length count */
       case Kzstr:    /* zero-terminated string */
         luaL_argerror(L, 1, "variable-length format");
-        break;
+        /* call never return, but to avoid warnings: *//* FALLTHROUGH */
       default:  break;
     }
   }

=== modified file 'src/third_party/eris/ltable.c'
--- src/third_party/eris/ltable.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/ltable.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.c,v 2.100 2015/01/05 13:52:37 roberto Exp $
+** $Id: ltable.c,v 2.117 2015/11/19 19:16:22 roberto Exp $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */
@@ -14,8 +14,8 @@
 ** Implementation of tables (aka arrays, objects, or hash tables).
 ** Tables keep its elements in two parts: an array part and a hash part.
 ** Non-negative integer keys are all candidates to be kept in the array
-** part. The actual size of the array is the largest 'n' such that at
-** least half the slots between 0 and n are in use.
+** part. The actual size of the array is the largest 'n' such that
+** more than half the slots between 1 and n are in use.
 ** Hash uses a mix of chained scatter table with Brent's variation.
 ** A main invariant of these tables is that, if an element is not
 ** in its main position (i.e. the 'original' position that its hash gives
@@ -23,9 +23,7 @@
 ** Hence even when the load factor reaches 100%, performance remains good.
 */
 
-#include <float.h>
 #include <math.h>
-#include <string.h>
 #include <limits.h>
 
 #include "lua.h"
@@ -71,7 +69,7 @@
 #define hashmod(t,n)	(gnode(t, ((n) % ((sizenode(t)-1)|1))))
 
 
-#define hashpointer(t,p)	hashmod(t, point2int(p))
+#define hashpointer(t,p)	hashmod(t, point2uint(p))
 
 
 #define dummynode		(&dummynode_)
@@ -85,31 +83,33 @@
 
 
 /*
-** Checks whether a float has a value representable as a lua_Integer
-** (and does the conversion if so)
-*/
-static int numisinteger (lua_Number x, lua_Integer *p) {
-  if ((x) == l_floor(x))  /* integral value? */
-    return lua_numbertointeger(x, p);  /* try as an integer */
-  else return 0;
-}
-
-
-/*
-** hash for floating-point numbers
-*/
-static Node *hashfloat (const Table *t, lua_Number n) {
+** Hash for floating-point numbers.
+** The main computation should be just
+**     n = frexp(n, &i); return (n * INT_MAX) + i
+** but there are some numerical subtleties.
+** In a two-complement representation, INT_MAX does not has an exact
+** representation as a float, but INT_MIN does; because the absolute
+** value of 'frexp' is smaller than 1 (unless 'n' is inf/NaN), the
+** absolute value of the product 'frexp * -INT_MIN' is smaller or equal
+** to INT_MAX. Next, the use of 'unsigned int' avoids overflows when
+** adding 'i'; the use of '~u' (instead of '-u') avoids problems with
+** INT_MIN.
+*/
+#if !defined(l_hashfloat)
+static int l_hashfloat (lua_Number n) {
   int i;
-  n = l_mathop(frexp)(n, &i) * cast_num(INT_MAX - DBL_MAX_EXP);
-  i += cast_int(n);
-  if (i < 0) {
-    if (cast(unsigned int, i) == 0u - i)  /* use unsigned to avoid overflows */
-      i = 0;  /* handle INT_MIN */
-    i = -i;  /* must be a positive value */
-  }
-  return hashmod(t, i);
+  lua_Integer ni;
+  n = l_mathop(frexp)(n, &i) * -cast_num(INT_MIN);
+  if (!lua_numbertointeger(n, &ni)) {  /* is 'n' inf/-inf/NaN? */
+    lua_assert(luai_numisnan(n) || l_mathop(fabs)(n) == cast_num(HUGE_VAL));
+    return 0;
+  }
+  else {  /* normal case */
+    unsigned int u = cast(unsigned int, i) + cast(unsigned int, ni);
+    return cast_int(u <= cast(unsigned int, INT_MAX) ? u : ~u);
+  }
 }
-
+#endif
 
 
 /*
@@ -121,17 +121,11 @@
     case LUA_TNUMINT:
       return hashint(t, ivalue(key));
     case LUA_TNUMFLT:
-      return hashfloat(t, fltvalue(key));
+      return hashmod(t, l_hashfloat(fltvalue(key)));
     case LUA_TSHRSTR:
       return hashstr(t, tsvalue(key));
-    case LUA_TLNGSTR: {
-      TString *s = tsvalue(key);
-      if (s->extra == 0) {  /* no hash? */
-        s->hash = luaS_hash(getstr(s), s->len, s->hash);
-        s->extra = 1;  /* now it has its hash */
-      }
-      return hashstr(t, tsvalue(key));
-    }
+    case LUA_TLNGSTR:
+      return hashpow2(t, luaS_hashlongstr(tsvalue(key)));
     case LUA_TBOOLEAN:
       return hashboolean(t, bvalue(key));
     case LUA_TLIGHTUSERDATA:
@@ -139,6 +133,7 @@
     case LUA_TLCF:
       return hashpointer(t, fvalue(key));
     default:
+      lua_assert(!ttisdeadkey(key));
       return hashpointer(t, gcvalue(key));
   }
 }
@@ -219,28 +214,29 @@
 /*
 ** Compute the optimal size for the array part of table 't'. 'nums' is a
 ** "count array" where 'nums[i]' is the number of integers in the table
-** between 2^(i - 1) + 1 and 2^i. Put in '*narray' the optimal size, and
-** return the number of elements that will go to that part.
+** between 2^(i - 1) + 1 and 2^i. 'pna' enters with the total number of
+** integer keys in the table and leaves with the number of keys that
+** will go to the array part; return the optimal size.
 */
-static unsigned int computesizes (unsigned int nums[], unsigned int *narray) {
+static unsigned int computesizes (unsigned int nums[], unsigned int *pna) {
   int i;
-  unsigned int twotoi;  /* 2^i */
+  unsigned int twotoi;  /* 2^i (candidate for optimal size) */
   unsigned int a = 0;  /* number of elements smaller than 2^i */
   unsigned int na = 0;  /* number of elements to go to array part */
-  unsigned int n = 0;  /* optimal size for array part */
-  for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) {
+  unsigned int optimal = 0;  /* optimal size for array part */
+  /* loop while keys can fill more than half of total size */
+  for (i = 0, twotoi = 1; *pna > twotoi / 2; i++, twotoi *= 2) {
     if (nums[i] > 0) {
       a += nums[i];
       if (a > twotoi/2) {  /* more than half elements present? */
-        n = twotoi;  /* optimal size (till now) */
-        na = a;  /* all elements up to 'n' will go to array part */
+        optimal = twotoi;  /* optimal size (till now) */
+        na = a;  /* all elements up to 'optimal' will go to array part */
       }
     }
-    if (a == *narray) break;  /* all elements already counted */
   }
-  *narray = n;
-  lua_assert(*narray/2 <= na && na <= *narray);
-  return na;
+  lua_assert((optimal == 0 || optimal / 2 < na) && na <= optimal);
+  *pna = na;
+  return optimal;
 }
 
 
@@ -255,6 +251,11 @@
 }
 
 
+/*
+** Count keys in array part of table 't': Fill 'nums[i]' with
+** number of keys that will go into corresponding slice and return
+** total number of non-nil keys.
+*/
 static unsigned int numusearray (const Table *t, unsigned int *nums) {
   int lg;
   unsigned int ttlg;  /* 2^lg */
@@ -281,8 +282,7 @@
 }
 
 
-static int numusehash (const Table *t, unsigned int *nums,
-                       unsigned int *pnasize) {
+static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) {
   int totaluse = 0;  /* total number of elements */
   int ause = 0;  /* elements added to 'nums' (can go to array part) */
   int i = sizenode(t);
@@ -293,7 +293,7 @@
       totaluse++;
     }
   }
-  *pnasize += ause;
+  *pna += ause;
   return totaluse;
 }
 
@@ -363,7 +363,7 @@
     }
   }
   if (!isdummy(nold))
-    luaM_freearray(L, nold, cast(size_t, twoto(oldhsize))); /* free old array */
+    luaM_freearray(L, nold, cast(size_t, twoto(oldhsize))); /* free old hash */
 }
 
 
@@ -376,21 +376,22 @@
 ** nums[i] = number of keys 'k' where 2^(i - 1) < k <= 2^i
 */
 static void rehash (lua_State *L, Table *t, const TValue *ek) {
-  unsigned int nasize, na;
+  unsigned int asize;  /* optimal size for array part */
+  unsigned int na;  /* number of keys in the array part */
   unsigned int nums[MAXABITS + 1];
   int i;
   int totaluse;
   for (i = 0; i <= MAXABITS; i++) nums[i] = 0;  /* reset counts */
-  nasize = numusearray(t, nums);  /* count keys in array part */
-  totaluse = nasize;  /* all those keys are integer keys */
-  totaluse += numusehash(t, nums, &nasize);  /* count keys in hash part */
+  na = numusearray(t, nums);  /* count keys in array part */
+  totaluse = na;  /* all those keys are integer keys */
+  totaluse += numusehash(t, nums, &na);  /* count keys in hash part */
   /* count extra key */
-  nasize += countint(ek, nums);
+  na += countint(ek, nums);
   totaluse++;
   /* compute new size for array part */
-  na = computesizes(nums, &nasize);
+  asize = computesizes(nums, &na);
   /* resize the table to new computed sizes */
-  luaH_resize(L, t, nasize, totaluse - na);
+  luaH_resize(L, t, asize, totaluse - na);
 }
 
 
@@ -443,14 +444,13 @@
   TValue aux;
   if (ttisnil(key)) luaG_runerror(L, "table index is nil");
   else if (ttisfloat(key)) {
-    lua_Number n = fltvalue(key);
     lua_Integer k;
-    if (luai_numisnan(n))
-      luaG_runerror(L, "table index is NaN");
-    if (numisinteger(n, &k)) {  /* index is int? */
+    if (luaV_tointeger(key, &k, 0)) {  /* index is int? */
       setivalue(&aux, k);
       key = &aux;  /* insert it as an integer */
     }
+    else if (luai_numisnan(fltvalue(key)))
+      luaG_runerror(L, "table index is NaN");
   }
   mp = mainposition(t, key);
   if (!ttisnil(gval(mp)) || isdummy(mp)) {  /* main position is taken? */
@@ -458,7 +458,7 @@
     Node *f = getfreepos(t);  /* get a free place */
     if (f == NULL) {  /* cannot find a free place? */
       rehash(L, t, key);  /* grow table */
-      /* whatever called 'newkey' takes care of TM cache and GC barrier */
+      /* whatever called 'newkey' takes care of TM cache */
       return luaH_set(L, t, key);  /* insert key into grown table */
     }
     lua_assert(!isdummy(f));
@@ -496,7 +496,7 @@
 */
 const TValue *luaH_getint (Table *t, lua_Integer key) {
   /* (1 <= key && key <= t->sizearray) */
-  if (l_castS2U(key - 1) < t->sizearray)
+  if (l_castS2U(key) - 1 < t->sizearray)
     return &t->array[key - 1];
   else {
     Node *n = hashint(t, key);
@@ -508,7 +508,7 @@
         if (nx == 0) break;
         n += nx;
       }
-    };
+    }
     return luaO_nilobject;
   }
 }
@@ -517,7 +517,7 @@
 /*
 ** search function for short strings
 */
-const TValue *luaH_getstr (Table *t, TString *key) {
+const TValue *luaH_getshortstr (Table *t, TString *key) {
   Node *n = hashstr(t, key);
   lua_assert(key->tt == LUA_TSHRSTR);
   for (;;) {  /* check whether 'key' is somewhere in the chain */
@@ -526,11 +526,41 @@
       return gval(n);  /* that's it */
     else {
       int nx = gnext(n);
-      if (nx == 0) break;
-      n += nx;
-    }
-  };
-  return luaO_nilobject;
+      if (nx == 0)
+        return luaO_nilobject;  /* not found */
+      n += nx;
+    }
+  }
+}
+
+
+/*
+** "Generic" get version. (Not that generic: not valid for integers,
+** which may be in array part, nor for floats with integral values.)
+*/
+static const TValue *getgeneric (Table *t, const TValue *key) {
+  Node *n = mainposition(t, key);
+  for (;;) {  /* check whether 'key' is somewhere in the chain */
+    if (luaV_rawequalobj(gkey(n), key))
+      return gval(n);  /* that's it */
+    else {
+      int nx = gnext(n);
+      if (nx == 0)
+        return luaO_nilobject;  /* not found */
+      n += nx;
+    }
+  }
+}
+
+
+const TValue *luaH_getstr (Table *t, TString *key) {
+  if (key->tt == LUA_TSHRSTR)
+    return luaH_getshortstr(t, key);
+  else {  /* for long strings, use generic case */
+    TValue ko;
+    setsvalue(cast(lua_State *, NULL), &ko, key);
+    return getgeneric(t, &ko);
+  }
 }
 
 
@@ -539,28 +569,17 @@
 */
 const TValue *luaH_get (Table *t, const TValue *key) {
   switch (ttype(key)) {
-    case LUA_TSHRSTR: return luaH_getstr(t, tsvalue(key));
+    case LUA_TSHRSTR: return luaH_getshortstr(t, tsvalue(key));
     case LUA_TNUMINT: return luaH_getint(t, ivalue(key));
     case LUA_TNIL: return luaO_nilobject;
     case LUA_TNUMFLT: {
       lua_Integer k;
-      if (numisinteger(fltvalue(key), &k)) /* index is int? */
+      if (luaV_tointeger(key, &k, 0)) /* index is int? */
         return luaH_getint(t, k);  /* use specialized version */
-      /* else go through */
-    }
-    default: {
-      Node *n = mainposition(t, key);
-      for (;;) {  /* check whether 'key' is somewhere in the chain */
-        if (luaV_rawequalobj(gkey(n), key))
-          return gval(n);  /* that's it */
-        else {
-          int nx = gnext(n);
-          if (nx == 0) break;
-          n += nx;
-        }
-      };
-      return luaO_nilobject;
-    }
+      /* else... */
+    }  /* FALLTHROUGH */
+    default:
+      return getgeneric(t, key);
   }
 }
 

=== modified file 'src/third_party/eris/ltable.h'
--- src/third_party/eris/ltable.h	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/ltable.h	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.h,v 2.20 2014/09/04 18:15:29 roberto Exp $
+** $Id: ltable.h,v 2.21 2015/11/03 15:47:30 roberto Exp $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */
@@ -18,6 +18,10 @@
 /* 'const' to avoid wrong writings that can mess up field 'next' */ 
 #define gkey(n)		cast(const TValue*, (&(n)->i_key.tvk))
 
+/*
+** writable version of 'gkey'; allows updates to individual fields,
+** but not to the whole (which has incompatible type)
+*/
 #define wgkey(n)		(&(n)->i_key.nk)
 
 #define invalidateTMcache(t)	((t)->flags = 0)
@@ -31,6 +35,7 @@
 LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key);
 LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key,
                                                     TValue *value);
+LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key);
 LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
 LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
 LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key);

=== modified file 'src/third_party/eris/ltablib.c'
--- src/third_party/eris/ltablib.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/ltablib.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: ltablib.c,v 1.79 2014/11/02 19:19:04 roberto Exp $
+** $Id: ltablib.c,v 1.90 2015/11/25 12:48:57 roberto Exp $
 ** Library for Table Manipulation
 ** See Copyright Notice in lua.h
 */
@@ -12,6 +12,7 @@
 
 #include <limits.h>
 #include <stddef.h>
+#include <string.h>
 
 #include "lua.h"
 
@@ -19,40 +20,42 @@
 #include "lualib.h"
 
 
-
-/*
-** Structure with table-access functions
-*/
-typedef struct {
-  int (*geti) (lua_State *L, int idx, lua_Integer n);
-  void (*seti) (lua_State *L, int idx, lua_Integer n);
-} TabA;
-
-
-/*
-** Check that 'arg' has a table and set access functions in 'ta' to raw
-** or non-raw according to the presence of corresponding metamethods.
-*/
-static void checktab (lua_State *L, int arg, TabA *ta) {
-  ta->geti = NULL; ta->seti = NULL;
-  if (lua_getmetatable(L, arg)) {
-    lua_pushliteral(L, "__index");  /* 'index' metamethod */
-    if (lua_rawget(L, -2) != LUA_TNIL)
-      ta->geti = lua_geti;
-    lua_pushliteral(L, "__newindex");  /* 'newindex' metamethod */
-    if (lua_rawget(L, -3) != LUA_TNIL)
-      ta->seti = lua_seti;
-    lua_pop(L, 3);  /* pop metatable plus both metamethods */
-  }
-  if (ta->geti == NULL || ta->seti == NULL) {
-    luaL_checktype(L, arg, LUA_TTABLE);  /* must be table for raw methods */
-    if (ta->geti == NULL) ta->geti = lua_rawgeti;
-    if (ta->seti == NULL) ta->seti = lua_rawseti;
-  }
-}
-
-
-#define aux_getn(L,n,ta)	(checktab(L, n, ta), luaL_len(L, n))
+/*
+** Operations that an object must define to mimic a table
+** (some functions only need some of them)
+*/
+#define TAB_R	1			/* read */
+#define TAB_W	2			/* write */
+#define TAB_L	4			/* length */
+#define TAB_RW	(TAB_R | TAB_W)		/* read/write */
+
+
+#define aux_getn(L,n,w)	(checktab(L, n, (w) | TAB_L), luaL_len(L, n))
+
+
+static int checkfield (lua_State *L, const char *key, int n) {
+  lua_pushstring(L, key);
+  return (lua_rawget(L, -n) != LUA_TNIL);
+}
+
+
+/*
+** Check that 'arg' either is a table or can behave like one (that is,
+** has a metatable with the required metamethods)
+*/
+static void checktab (lua_State *L, int arg, int what) {
+  if (lua_type(L, arg) != LUA_TTABLE) {  /* is it not a table? */
+    int n = 1;  /* number of elements to pop */
+    if (lua_getmetatable(L, arg) &&  /* must have metatable */
+        (!(what & TAB_R) || checkfield(L, "__index", ++n)) &&
+        (!(what & TAB_W) || checkfield(L, "__newindex", ++n)) &&
+        (!(what & TAB_L) || checkfield(L, "__len", ++n))) {
+      lua_pop(L, n);  /* pop metatable and tested metamethods */
+    }
+    else
+      luaL_argerror(L, arg, "table expected");  /* force an error */
+  }
+}
 
 
 #if defined(LUA_COMPAT_MAXN)
@@ -74,8 +77,7 @@
 
 
 static int tinsert (lua_State *L) {
-  TabA ta;
-  lua_Integer e = aux_getn(L, 1, &ta) + 1;  /* first empty element */
+  lua_Integer e = aux_getn(L, 1, TAB_RW) + 1;  /* first empty element */
   lua_Integer pos;  /* where to insert new element */
   switch (lua_gettop(L)) {
     case 2: {  /* called with only 2 arguments */
@@ -87,8 +89,8 @@
       pos = luaL_checkinteger(L, 2);  /* 2nd argument is the position */
       luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds");
       for (i = e; i > pos; i--) {  /* move up elements */
-        (*ta.geti)(L, 1, i - 1);
-        (*ta.seti)(L, 1, i);  /* t[i] = t[i - 1] */
+        lua_geti(L, 1, i - 1);
+        lua_seti(L, 1, i);  /* t[i] = t[i - 1] */
       }
       break;
     }
@@ -96,55 +98,57 @@
       return luaL_error(L, "wrong number of arguments to 'insert'");
     }
   }
-  (*ta.seti)(L, 1, pos);  /* t[pos] = v */
+  lua_seti(L, 1, pos);  /* t[pos] = v */
   return 0;
 }
 
 
 static int tremove (lua_State *L) {
-  TabA ta;
-  lua_Integer size = aux_getn(L, 1, &ta);
+  lua_Integer size = aux_getn(L, 1, TAB_RW);
   lua_Integer pos = luaL_optinteger(L, 2, size);
   if (pos != size)  /* validate 'pos' if given */
     luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds");
-  (*ta.geti)(L, 1, pos);  /* result = t[pos] */
+  lua_geti(L, 1, pos);  /* result = t[pos] */
   for ( ; pos < size; pos++) {
-    (*ta.geti)(L, 1, pos + 1);
-    (*ta.seti)(L, 1, pos);  /* t[pos] = t[pos + 1] */
+    lua_geti(L, 1, pos + 1);
+    lua_seti(L, 1, pos);  /* t[pos] = t[pos + 1] */
   }
   lua_pushnil(L);
-  (*ta.seti)(L, 1, pos);  /* t[pos] = nil */
+  lua_seti(L, 1, pos);  /* t[pos] = nil */
   return 1;
 }
 
 
+/*
+** Copy elements (1[f], ..., 1[e]) into (tt[t], tt[t+1], ...). Whenever
+** possible, copy in increasing order, which is better for rehashing.
+** "possible" means destination after original range, or smaller
+** than origin, or copying to another table.
+*/
 static int tmove (lua_State *L) {
-  TabA ta;
   lua_Integer f = luaL_checkinteger(L, 2);
   lua_Integer e = luaL_checkinteger(L, 3);
   lua_Integer t = luaL_checkinteger(L, 4);
   int tt = !lua_isnoneornil(L, 5) ? 5 : 1;  /* destination table */
-  /* the following restriction avoids several problems with overflows */
-  luaL_argcheck(L, f > 0, 2, "initial position must be positive");
+  checktab(L, 1, TAB_R);
+  checktab(L, tt, TAB_W);
   if (e >= f) {  /* otherwise, nothing to move */
     lua_Integer n, i;
-    ta.geti = (luaL_getmetafield(L, 1, "__index") == LUA_TNIL)
-      ? (luaL_checktype(L, 1, LUA_TTABLE), lua_rawgeti)
-      : lua_geti;
-    ta.seti = (luaL_getmetafield(L, tt, "__newindex") == LUA_TNIL)
-      ? (luaL_checktype(L, tt, LUA_TTABLE), lua_rawseti)
-      : lua_seti;
+    luaL_argcheck(L, f > 0 || e < LUA_MAXINTEGER + f, 3,
+                  "too many elements to move");
     n = e - f + 1;  /* number of elements to move */
-    if (t > f) {
+    luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4,
+                  "destination wrap around");
+    if (t > e || t <= f || tt != 1) {
+      for (i = 0; i < n; i++) {
+        lua_geti(L, 1, f + i);
+        lua_seti(L, tt, t + i);
+      }
+    }
+    else {
       for (i = n - 1; i >= 0; i--) {
-        (*ta.geti)(L, 1, f + i);
-        (*ta.seti)(L, tt, t + i);
-      }
-    }
-    else {
-      for (i = 0; i < n; i++) {
-        (*ta.geti)(L, 1, f + i);
-        (*ta.seti)(L, tt, t + i);
+        lua_geti(L, 1, f + i);
+        lua_seti(L, tt, t + i);
       }
     }
   }
@@ -153,8 +157,8 @@
 }
 
 
-static void addfield (lua_State *L, luaL_Buffer *b, TabA *ta, lua_Integer i) {
-  (*ta->geti)(L, 1, i);
+static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) {
+  lua_geti(L, 1, i);
   if (!lua_isstring(L, -1))
     luaL_error(L, "invalid value (%s) at index %d in table for 'concat'",
                   luaL_typename(L, -1), i);
@@ -163,21 +167,19 @@
 
 
 static int tconcat (lua_State *L) {
-  TabA ta;
   luaL_Buffer b;
+  lua_Integer last = aux_getn(L, 1, TAB_R);
   size_t lsep;
-  lua_Integer i, last;
   const char *sep = luaL_optlstring(L, 2, "", &lsep);
-  checktab(L, 1, &ta);
-  i = luaL_optinteger(L, 3, 1);
-  last = luaL_opt(L, luaL_checkinteger, 4, luaL_len(L, 1));
+  lua_Integer i = luaL_optinteger(L, 3, 1);
+  last = luaL_opt(L, luaL_checkinteger, 4, last);
   luaL_buffinit(L, &b);
   for (; i < last; i++) {
-    addfield(L, &b, &ta, i);
+    addfield(L, &b, i);
     luaL_addlstring(&b, sep, lsep);
   }
   if (i == last)  /* add last value (if interval was not empty) */
-    addfield(L, &b, &ta, i);
+    addfield(L, &b, i);
   luaL_pushresult(&b);
   return 1;
 }
@@ -195,7 +197,7 @@
   lua_createtable(L, n, 1);  /* create result table */
   lua_insert(L, 1);  /* put it at index 1 */
   for (i = n; i >= 1; i--)  /* assign elements */
-    lua_rawseti(L, 1, i);
+    lua_seti(L, 1, i);
   lua_pushinteger(L, n);
   lua_setfield(L, 1, "n");  /* t.n = number of elements */
   return 1;  /* return table */
@@ -203,20 +205,17 @@
 
 
 static int unpack (lua_State *L) {
-  TabA ta;
-  lua_Integer i, e;
   lua_Unsigned n;
-  checktab(L, 1, &ta);
-  i = luaL_optinteger(L, 2, 1);
-  e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1));
+  lua_Integer i = luaL_optinteger(L, 2, 1);
+  lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1));
   if (i > e) return 0;  /* empty range */
   n = (lua_Unsigned)e - i;  /* number of elements minus 1 (avoid overflows) */
   if (n >= (unsigned int)INT_MAX  || !lua_checkstack(L, (int)(++n)))
     return luaL_error(L, "too many results to unpack");
-  do {  /* must have at least one element */
-    (*ta.geti)(L, 1, i);  /* push arg[i..e] */
-  } while (i++ < e); 
-
+  for (; i < e; i++) {  /* push arg[i..e - 1] (to avoid overflows) */
+    lua_geti(L, 1, i);
+  }
+  lua_geti(L, 1, e);  /* push last element */
   return (int)n;
 }
 
@@ -233,97 +232,190 @@
 */
 
 
-static void set2 (lua_State *L, TabA *ta, int i, int j) {
-  (*ta->seti)(L, 1, i);
-  (*ta->seti)(L, 1, j);
-}
-
+/*
+** Produce a "random" 'unsigned int' to randomize pivot choice. This
+** macro is used only when 'sort' detects a big imbalance in the result
+** of a partition. (If you don't want/need this "randomness", ~0 is a
+** good choice.)
+*/
+#if !defined(l_randomizePivot)		/* { */
+
+#include <time.h>
+
+/* size of 'e' measured in number of 'unsigned int's */
+#define sof(e)		(sizeof(e) / sizeof(unsigned int))
+
+/*
+** Use 'time' and 'clock' as sources of "randomness". Because we don't
+** know the types 'clock_t' and 'time_t', we cannot cast them to
+** anything without risking overflows. A safe way to use their values
+** is to copy them to an array of a known type and use the array values.
+*/
+static unsigned int l_randomizePivot (void) {
+  clock_t c = clock();
+  time_t t = time(NULL);
+  unsigned int buff[sof(c) + sof(t)];
+  unsigned int i, rnd = 0;
+  memcpy(buff, &c, sof(c) * sizeof(unsigned int));
+  memcpy(buff + sof(c), &t, sof(t) * sizeof(unsigned int));
+  for (i = 0; i < sof(buff); i++)
+    rnd += buff[i];
+  return rnd;
+}
+
+#endif					/* } */
+
+
+/* arrays larger than 'RANLIMIT' may use randomized pivots */
+#define RANLIMIT	100u
+
+
+static void set2 (lua_State *L, unsigned int i, unsigned int j) {
+  lua_seti(L, 1, i);
+  lua_seti(L, 1, j);
+}
+
+
+/*
+** Return true iff value at stack index 'a' is less than the value at
+** index 'b' (according to the order of the sort).
+*/
 static int sort_comp (lua_State *L, int a, int b) {
-  if (!lua_isnil(L, 2)) {  /* function? */
+  if (lua_isnil(L, 2))  /* no function? */
+    return lua_compare(L, a, b, LUA_OPLT);  /* a < b */
+  else {  /* function */
     int res;
-    lua_pushvalue(L, 2);
+    lua_pushvalue(L, 2);    /* push function */
     lua_pushvalue(L, a-1);  /* -1 to compensate function */
     lua_pushvalue(L, b-2);  /* -2 to compensate function and 'a' */
-    lua_call(L, 2, 1);
-    res = lua_toboolean(L, -1);
-    lua_pop(L, 1);
+    lua_call(L, 2, 1);      /* call function */
+    res = lua_toboolean(L, -1);  /* get result */
+    lua_pop(L, 1);          /* pop result */
     return res;
   }
-  else  /* a < b? */
-    return lua_compare(L, a, b, LUA_OPLT);
-}
-
-static void auxsort (lua_State *L, TabA *ta, int l, int u) {
-  while (l < u) {  /* for tail recursion */
-    int i, j;
-    /* sort elements a[l], a[(l+u)/2] and a[u] */
-    (*ta->geti)(L, 1, l);
-    (*ta->geti)(L, 1, u);
-    if (sort_comp(L, -1, -2))  /* a[u] < a[l]? */
-      set2(L, ta, l, u);  /* swap a[l] - a[u] */
+}
+
+
+/*
+** Does the partition: Pivot P is at the top of the stack.
+** precondition: a[lo] <= P == a[up-1] <= a[up],
+** so it only needs to do the partition from lo + 1 to up - 2.
+** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up]
+** returns 'i'.
+*/
+static unsigned int partition (lua_State *L, unsigned int lo,
+                                             unsigned int up) {
+  unsigned int i = lo;  /* will be incremented before first use */
+  unsigned int j = up - 1;  /* will be decremented before first use */
+  /* loop invariant: a[lo .. i] <= P <= a[j .. up] */
+  for (;;) {
+    /* next loop: repeat ++i while a[i] < P */
+    while (lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) {
+      if (i == up - 1)  /* a[i] < P  but a[up - 1] == P  ?? */
+        luaL_error(L, "invalid order function for sorting");
+      lua_pop(L, 1);  /* remove a[i] */
+    }
+    /* after the loop, a[i] >= P and a[lo .. i - 1] < P */
+    /* next loop: repeat --j while P < a[j] */
+    while (lua_geti(L, 1, --j), sort_comp(L, -3, -1)) {
+      if (j < i)  /* j < i  but  a[j] > P ?? */
+        luaL_error(L, "invalid order function for sorting");
+      lua_pop(L, 1);  /* remove a[j] */
+    }
+    /* after the loop, a[j] <= P and a[j + 1 .. up] >= P */
+    if (j < i) {  /* no elements out of place? */
+      /* a[lo .. i - 1] <= P <= a[j + 1 .. i .. up] */
+      lua_pop(L, 1);  /* pop a[j] */
+      /* swap pivot (a[up - 1]) with a[i] to satisfy pos-condition */
+      set2(L, up - 1, i);
+      return i;
+    }
+    /* otherwise, swap a[i] - a[j] to restore invariant and repeat */
+    set2(L, i, j);
+  }
+}
+
+
+/*
+** Choose an element in the middle (2nd-3th quarters) of [lo,up]
+** "randomized" by 'rnd'
+*/
+static unsigned int choosePivot (unsigned int lo, unsigned int up,
+                                 unsigned int rnd) {
+  unsigned int r4 = (unsigned int)(up - lo) / 4u;  /* range/4 */
+  unsigned int p = rnd % (r4 * 2) + (lo + r4);
+  lua_assert(lo + r4 <= p && p <= up - r4);
+  return p;
+}
+
+
+/*
+** QuickSort algorithm (recursive function)
+*/
+static void auxsort (lua_State *L, unsigned int lo, unsigned int up,
+                                   unsigned int rnd) {
+  while (lo < up) {  /* loop for tail recursion */
+    unsigned int p;  /* Pivot index */
+    unsigned int n;  /* to be used later */
+    /* sort elements 'lo', 'p', and 'up' */
+    lua_geti(L, 1, lo);
+    lua_geti(L, 1, up);
+    if (sort_comp(L, -1, -2))  /* a[up] < a[lo]? */
+      set2(L, lo, up);  /* swap a[lo] - a[up] */
     else
-      lua_pop(L, 2);
-    if (u-l == 1) break;  /* only 2 elements */
-    i = (l+u)/2;
-    (*ta->geti)(L, 1, i);
-    (*ta->geti)(L, 1, l);
-    if (sort_comp(L, -2, -1))  /* a[i]<a[l]? */
-      set2(L, ta, i, l);
+      lua_pop(L, 2);  /* remove both values */
+    if (up - lo == 1)  /* only 2 elements? */
+      return;  /* already sorted */
+    if (up - lo < RANLIMIT || rnd == 0)  /* small interval or no randomize? */
+      p = (lo + up)/2;  /* middle element is a good pivot */
+    else  /* for larger intervals, it is worth a random pivot */
+      p = choosePivot(lo, up, rnd);
+    lua_geti(L, 1, p);
+    lua_geti(L, 1, lo);
+    if (sort_comp(L, -2, -1))  /* a[p] < a[lo]? */
+      set2(L, p, lo);  /* swap a[p] - a[lo] */
     else {
-      lua_pop(L, 1);  /* remove a[l] */
-      (*ta->geti)(L, 1, u);
-      if (sort_comp(L, -1, -2))  /* a[u]<a[i]? */
-        set2(L, ta, i, u);
+      lua_pop(L, 1);  /* remove a[lo] */
+      lua_geti(L, 1, up);
+      if (sort_comp(L, -1, -2))  /* a[up] < a[p]? */
+        set2(L, p, up);  /* swap a[up] - a[p] */
       else
         lua_pop(L, 2);
     }
-    if (u-l == 2) break;  /* only 3 elements */
-    (*ta->geti)(L, 1, i);  /* Pivot */
-    lua_pushvalue(L, -1);
-    (*ta->geti)(L, 1, u-1);
-    set2(L, ta, i, u-1);
-    /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */
-    i = l; j = u-1;
-    for (;;) {  /* invariant: a[l..i] <= P <= a[j..u] */
-      /* repeat ++i until a[i] >= P */
-      while ((*ta->geti)(L, 1, ++i), sort_comp(L, -1, -2)) {
-        if (i>=u) luaL_error(L, "invalid order function for sorting");
-        lua_pop(L, 1);  /* remove a[i] */
-      }
-      /* repeat --j until a[j] <= P */
-      while ((*ta->geti)(L, 1, --j), sort_comp(L, -3, -1)) {
-        if (j<=l) luaL_error(L, "invalid order function for sorting");
-        lua_pop(L, 1);  /* remove a[j] */
-      }
-      if (j<i) {
-        lua_pop(L, 3);  /* pop pivot, a[i], a[j] */
-        break;
-      }
-      set2(L, ta, i, j);
-    }
-    (*ta->geti)(L, 1, u-1);
-    (*ta->geti)(L, 1, i);
-    set2(L, ta, u-1, i);  /* swap pivot (a[u-1]) with a[i] */
-    /* a[l..i-1] <= a[i] == P <= a[i+1..u] */
-    /* adjust so that smaller half is in [j..i] and larger one in [l..u] */
-    if (i-l < u-i) {
-      j=l; i=i-1; l=i+2;
+    if (up - lo == 2)  /* only 3 elements? */
+      return;  /* already sorted */
+    lua_geti(L, 1, p);  /* get middle element (Pivot) */
+    lua_pushvalue(L, -1);  /* push Pivot */
+    lua_geti(L, 1, up - 1);  /* push a[up - 1] */
+    set2(L, p, up - 1);  /* swap Pivot (a[p]) with a[up - 1] */
+    p = partition(L, lo, up);
+    /* a[lo .. p - 1] <= a[p] == P <= a[p + 1 .. up] */
+    if (p - lo < up - p) {  /* lower interval is smaller? */
+      auxsort(L, lo, p - 1, rnd);  /* call recursively for lower interval */
+      n = p - lo;  /* size of smaller interval */
+      lo = p + 1;  /* tail call for [p + 1 .. up] (upper interval) */
     }
     else {
-      j=i+1; i=u; u=j-2;
+      auxsort(L, p + 1, up, rnd);  /* call recursively for upper interval */
+      n = up - p;  /* size of smaller interval */
+      up = p - 1;  /* tail call for [lo .. p - 1]  (lower interval) */
     }
-    auxsort(L, ta, j, i);  /* call recursively the smaller one */
-  }  /* repeat the routine for the larger one */
+    if ((up - lo) / 128u > n) /* partition too imbalanced? */
+      rnd = l_randomizePivot();  /* try a new randomization */
+  }  /* tail call auxsort(L, lo, up, rnd) */
 }
 
+
 static int sort (lua_State *L) {
-  TabA ta;
-  int n = (int)aux_getn(L, 1, &ta);
-  luaL_checkstack(L, 50, "");  /* assume array is smaller than 2^50 */
-  if (!lua_isnoneornil(L, 2))  /* is there a 2nd argument? */
-    luaL_checktype(L, 2, LUA_TFUNCTION);
-  lua_settop(L, 2);  /* make sure there are two arguments */
-  auxsort(L, &ta, 1, n);
+  lua_Integer n = aux_getn(L, 1, TAB_RW);
+  if (n > 1) {  /* non-trivial interval? */
+    luaL_argcheck(L, n < INT_MAX, 1, "array too big");
+    luaL_checkstack(L, 40, "");  /* assume array is smaller than 2^40 */
+    if (!lua_isnoneornil(L, 2))  /* is there a 2nd argument? */
+      luaL_checktype(L, 2, LUA_TFUNCTION);  /* must be a function */
+    lua_settop(L, 2);  /* make sure there are two arguments */
+    auxsort(L, 1, (unsigned int)n, 0u);
+  }
   return 0;
 }
 

=== modified file 'src/third_party/eris/ltm.c'
--- src/third_party/eris/ltm.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/ltm.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.c,v 2.33 2014/11/21 12:15:57 roberto Exp $
+** $Id: ltm.c,v 2.36 2015/11/03 15:47:30 roberto Exp $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */
@@ -57,7 +57,7 @@
 ** tag methods
 */
 const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
-  const TValue *tm = luaH_getstr(events, ename);
+  const TValue *tm = luaH_getshortstr(events, ename);
   lua_assert(event <= TM_EQ);
   if (ttisnil(tm)) {  /* no tag method? */
     events->flags |= cast_byte(1u<<event);  /* cache this fact */
@@ -79,20 +79,25 @@
     default:
       mt = G(L)->mt[ttnov(o)];
   }
-  return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject);
+  return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : luaO_nilobject);
 }
 
 
 void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
                   const TValue *p2, TValue *p3, int hasres) {
   ptrdiff_t result = savestack(L, p3);
-  setobj2s(L, L->top++, f);  /* push function (assume EXTRA_STACK) */
-  setobj2s(L, L->top++, p1);  /* 1st argument */
-  setobj2s(L, L->top++, p2);  /* 2nd argument */
+  StkId func = L->top;
+  setobj2s(L, func, f);  /* push function (assume EXTRA_STACK) */
+  setobj2s(L, func + 1, p1);  /* 1st argument */
+  setobj2s(L, func + 2, p2);  /* 2nd argument */
+  L->top += 3;
   if (!hasres)  /* no result? 'p3' is third argument */
     setobj2s(L, L->top++, p3);  /* 3rd argument */
   /* metamethod may yield only when called from Lua code */
-  luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci));
+  if (isLua(L->ci))
+    luaD_call(L, func, hasres);
+  else
+    luaD_callnoyield(L, func, hasres);
   if (hasres) {  /* if has result, move it to its place */
     p3 = restorestack(L, result);
     setobjs2s(L, p3, --L->top);
@@ -117,6 +122,7 @@
     switch (event) {
       case TM_CONCAT:
         luaG_concaterror(L, p1, p2);
+      /* call never returns, but to avoid warnings: *//* FALLTHROUGH */
       case TM_BAND: case TM_BOR: case TM_BXOR:
       case TM_SHL: case TM_SHR: case TM_BNOT: {
         lua_Number dummy;
@@ -124,8 +130,8 @@
           luaG_tointerror(L, p1, p2);
         else
           luaG_opinterror(L, p1, p2, "perform bitwise operation on");
-        /* else go through */
       }
+      /* calls never return, but to avoid warnings: *//* FALLTHROUGH */
       default:
         luaG_opinterror(L, p1, p2, "perform arithmetic on");
     }

=== modified file 'src/third_party/eris/lua.c'
--- src/third_party/eris/lua.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lua.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lua.c,v 1.222 2014/11/11 19:41:27 roberto Exp $
+** $Id: lua.c,v 1.226 2015/08/14 19:11:20 roberto Exp $
 ** Lua stand-alone interpreter
 ** See Copyright Notice in lua.h
 */
@@ -80,9 +80,7 @@
 #include <readline/readline.h>
 #include <readline/history.h>
 #define lua_readline(L,b,p)	((void)L, ((b)=readline(p)) != NULL)
-#define lua_saveline(L,idx) \
-        if (lua_rawlen(L,idx) > 0)  /* non-empty line? */ \
-          add_history(lua_tostring(L, idx));  /* add it to history */
+#define lua_saveline(L,line)	((void)L, add_history(line))
 #define lua_freeline(L,b)	((void)L, free(b))
 
 #else				/* }{ */
@@ -90,7 +88,7 @@
 #define lua_readline(L,b,p) \
         ((void)L, fputs(p, stdout), fflush(stdout),  /* show prompt */ \
         fgets(b, LUA_MAXINPUT, stdin) != NULL)  /* get line */
-#define lua_saveline(L,idx)	{ (void)L; (void)idx; }
+#define lua_saveline(L,line)	{ (void)L; (void)line; }
 #define lua_freeline(L,b)	{ (void)L; (void)b; }
 
 #endif				/* } */
@@ -315,31 +313,31 @@
   lua_pop(L, 1);  /* remove prompt */
   l = strlen(b);
   if (l > 0 && b[l-1] == '\n')  /* line ends with newline? */
-    b[l-1] = '\0';  /* remove it */
+    b[--l] = '\0';  /* remove it */
   if (firstline && b[0] == '=')  /* for compatibility with 5.2, ... */
     lua_pushfstring(L, "return %s", b + 1);  /* change '=' to 'return' */
   else
-    lua_pushstring(L, b);
+    lua_pushlstring(L, b, l);
   lua_freeline(L, b);
   return 1;
 }
 
 
 /*
-** Try to compile line on the stack as 'return <line>'; on return, stack
+** Try to compile line on the stack as 'return <line>;'; on return, stack
 ** has either compiled chunk or original line (if compilation failed).
 */
 static int addreturn (lua_State *L) {
-  int status;
-  size_t len; const char *line;
-  lua_pushliteral(L, "return ");
-  lua_pushvalue(L, -2);  /* duplicate line */
-  lua_concat(L, 2);  /* new line is "return ..." */
-  line = lua_tolstring(L, -1, &len);
-  if ((status = luaL_loadbuffer(L, line, len, "=stdin")) == LUA_OK)
-    lua_remove(L, -3);  /* remove original line */
+  const char *line = lua_tostring(L, -1);  /* original line */
+  const char *retline = lua_pushfstring(L, "return %s;", line);
+  int status = luaL_loadbuffer(L, retline, strlen(retline), "=stdin");
+  if (status == LUA_OK) {
+    lua_remove(L, -2);  /* remove modified line */
+    if (line[0] != '\0')  /* non empty? */
+      lua_saveline(L, line);  /* keep history */
+  }
   else
-    lua_pop(L, 2);  /* remove result from 'luaL_loadbuffer' and new line */
+    lua_pop(L, 2);  /* pop result from 'luaL_loadbuffer' and modified line */
   return status;
 }
 
@@ -352,8 +350,10 @@
     size_t len;
     const char *line = lua_tolstring(L, 1, &len);  /* get what it has */
     int status = luaL_loadbuffer(L, line, len, "=stdin");  /* try it */
-    if (!incomplete(L, status) || !pushline(L, 0))
+    if (!incomplete(L, status) || !pushline(L, 0)) {
+      lua_saveline(L, line);  /* keep history */
       return status;  /* cannot or should not try to add continuation line */
+    }
     lua_pushliteral(L, "\n");  /* add newline... */
     lua_insert(L, -2);  /* ...between the two lines */
     lua_concat(L, 3);  /* join them */
@@ -374,7 +374,6 @@
     return -1;  /* no input */
   if ((status = addreturn(L)) != LUA_OK)  /* 'return ...' did not work? */
     status = multiline(L);  /* try as command, maybe with continuation lines */
-  lua_saveline(L, 1);  /* keep history */
   lua_remove(L, 1);  /* remove line from the stack */
   lua_assert(lua_gettop(L) == 1);
   return status;
@@ -482,14 +481,14 @@
         args |= has_E;
         break;
       case 'i':
-        args |= has_i;  /* goes through  (-i implies -v) */
+        args |= has_i;  /* (-i implies -v) *//* FALLTHROUGH */ 
       case 'v':
         if (argv[i][2] != '\0')  /* extra characters after 1st? */
           return has_error;  /* invalid option */
         args |= has_v;
         break;
       case 'e':
-        args |= has_e;  /* go through */
+        args |= has_e;  /* FALLTHROUGH */
       case 'l':  /* both options need an argument */
         if (argv[i][2] == '\0') {  /* no concatenated argument? */
           i++;  /* try next 'argv' */
@@ -513,17 +512,16 @@
 static int runargs (lua_State *L, char **argv, int n) {
   int i;
   for (i = 1; i < n; i++) {
-    int status;
     int option = argv[i][1];
     lua_assert(argv[i][0] == '-');  /* already checked */
     if (option == 'e' || option == 'l') {
+      int status;
       const char *extra = argv[i] + 2;  /* both options need an argument */
       if (*extra == '\0') extra = argv[++i];
       lua_assert(extra != NULL);
-      if (option == 'e')
-        status = dostring(L, extra, "=(command line)");
-      else
-        status = dolibrary(L, extra);
+      status = (option == 'e')
+               ? dostring(L, extra, "=(command line)")
+               : dolibrary(L, extra);
       if (status != LUA_OK) return 0;
     }
   }

=== modified file 'src/third_party/eris/lua.h'
--- src/third_party/eris/lua.h	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lua.h	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lua.h,v 1.325 2014/12/26 17:24:27 roberto Exp $
+** $Id: lua.h,v 1.329 2015/11/13 17:18:42 roberto Exp $
 ** Lua - A Scripting Language
 ** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
 ** See Copyright Notice at the end of this file
@@ -19,7 +19,7 @@
 #define LUA_VERSION_MAJOR	"5"
 #define LUA_VERSION_MINOR	"3"
 #define LUA_VERSION_NUM		503
-#define LUA_VERSION_RELEASE	"0"
+#define LUA_VERSION_RELEASE	"2"
 
 #define LUA_VERSION	"Lua+Eris " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
 #define LUA_RELEASE	LUA_VERSION "." LUA_VERSION_RELEASE
@@ -35,9 +35,11 @@
 
 
 /*
-** pseudo-indices
+** Pseudo-indices
+** (-LUAI_MAXSTACK is the minimum valid index; we keep some free empty
+** space after that to help overflow detection)
 */
-#define LUA_REGISTRYINDEX	LUAI_FIRSTPSEUDOIDX
+#define LUA_REGISTRYINDEX	(-LUAI_MAXSTACK - 1000)
 #define lua_upvalueindex(i)	(LUA_REGISTRYINDEX - (i))
 
 
@@ -356,8 +358,7 @@
 #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_pushliteral(L, s)	lua_pushstring(L, "" s)
 
 #define lua_pushglobaltable(L)  \
 	lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)

=== modified file 'src/third_party/eris/luac.c'
--- src/third_party/eris/luac.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/luac.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: luac.c,v 1.72 2015/01/06 03:09:13 lhf Exp $
+** $Id: luac.c,v 1.75 2015/03/12 01:58:27 lhf Exp $
 ** Lua compiler (saves bytecodes to files; also lists bytecodes)
 ** See Copyright Notice in lua.h
 */
@@ -206,7 +206,7 @@
 }
 
 /*
-** $Id: print.c,v 1.76 2015/01/05 16:12:50 lhf Exp $
+** $Id: luac.c,v 1.75 2015/03/12 01:58:27 lhf Exp $
 ** print bytecodes
 ** See Copyright Notice in lua.h
 */
@@ -226,7 +226,7 @@
 static void PrintString(const TString* ts)
 {
  const char* s=getstr(ts);
- size_t i,n=ts->len;
+ size_t i,n=tsslen(ts);
  printf("%c",'"');
  for (i=0; i<n; i++)
  {

=== modified file 'src/third_party/eris/luaconf.h'
--- src/third_party/eris/luaconf.h	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/luaconf.h	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: luaconf.h,v 1.238 2014/12/29 13:27:55 roberto Exp $
+** $Id: luaconf.h,v 1.254 2015/10/21 18:17:40 roberto Exp $
 ** Configuration file for Lua
 ** See Copyright Notice in lua.h
 */
@@ -96,10 +96,8 @@
 
 
 /*
-@@ LUA_INT_INT / LUA_INT_LONG / LUA_INT_LONGLONG defines the type for
-** Lua integers.
-@@ LUA_REAL_FLOAT / LUA_REAL_DOUBLE / LUA_REAL_LONGDOUBLE defines
-** the type for Lua floats.
+@@ LUA_INT_TYPE defines the type for Lua integers.
+@@ LUA_FLOAT_TYPE defines the type for Lua floats.
 ** Lua should work fine with any mix of these options (if supported
 ** by your C compiler). The usual configurations are 64-bit integers
 ** and 'double' (the default), 32-bit integers and 'float' (for
@@ -107,32 +105,47 @@
 ** compliant with C99, which may not have support for 'long long').
 */
 
+/* predefined options for LUA_INT_TYPE */
+#define LUA_INT_INT		1
+#define LUA_INT_LONG		2
+#define LUA_INT_LONGLONG	3
+
+/* predefined options for LUA_FLOAT_TYPE */
+#define LUA_FLOAT_FLOAT		1
+#define LUA_FLOAT_DOUBLE	2
+#define LUA_FLOAT_LONGDOUBLE	3
+
 #if defined(LUA_32BITS)		/* { */
 /*
 ** 32-bit integers and 'float'
 */
 #if LUAI_BITSINT >= 32  /* use 'int' if big enough */
-#define LUA_INT_INT
+#define LUA_INT_TYPE	LUA_INT_INT
 #else  /* otherwise use 'long' */
-#define LUA_INT_LONG
+#define LUA_INT_TYPE	LUA_INT_LONG
 #endif
-#define LUA_REAL_FLOAT
+#define LUA_FLOAT_TYPE	LUA_FLOAT_FLOAT
 
 #elif defined(LUA_C89_NUMBERS)	/* }{ */
 /*
 ** largest types available for C89 ('long' and 'double')
 */
-#define LUA_INT_LONG
-#define LUA_REAL_DOUBLE
-
-#else				/* }{ */
+#define LUA_INT_TYPE	LUA_INT_LONG
+#define LUA_FLOAT_TYPE	LUA_FLOAT_DOUBLE
+
+#endif				/* } */
+
+
 /*
 ** default configuration for 64-bit Lua ('long long' and 'double')
 */
-#define LUA_INT_LONGLONG
-#define LUA_REAL_DOUBLE
+#if !defined(LUA_INT_TYPE)
+#define LUA_INT_TYPE	LUA_INT_LONGLONG
+#endif
 
-#endif								/* } */
+#if !defined(LUA_FLOAT_TYPE)
+#define LUA_FLOAT_TYPE	LUA_FLOAT_DOUBLE
+#endif
 
 /* }================================================================== */
 
@@ -155,7 +168,7 @@
 ** non-conventional directories.
 */
 #define LUA_VDIR	LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
-#if defined(_WIN32) 	/* { */
+#if defined(_WIN32)	/* { */
 /*
 ** In Windows, any exclamation mark ('!') in the path is replaced by the
 ** path of the directory of the executable file of the current process.
@@ -300,20 +313,15 @@
 */
 #define LUA_COMPAT_APIINTCASTS
 
-
-/*
-@@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a
-@@ a float mark ('.0').
-** This macro is not on by default even in compatibility mode,
-** because this is not really an incompatibility.
-*/
-/* #define LUA_COMPAT_FLOATSTRING */
-
 #endif				/* } */
 
 
 #if defined(LUA_COMPAT_5_1)	/* { */
 
+/* Incompatibilities from 5.2 -> 5.3 */
+#define LUA_COMPAT_MATHLIB
+#define LUA_COMPAT_APIINTCASTS
+
 /*
 @@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'.
 ** You can replace it with 'table.unpack'.
@@ -373,6 +381,15 @@
 
 #endif				/* } */
 
+
+/*
+@@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a
+@@ a float mark ('.0').
+** This macro is not on by default even in compatibility mode,
+** because this is not really an incompatibility.
+*/
+/* #define LUA_COMPAT_FLOATSTRING */
+
 /* }================================================================== */
 
 
@@ -380,30 +397,54 @@
 /*
 ** {==================================================================
 ** Configuration for Numbers.
-** Change these definitions if no predefined LUA_REAL_* / LUA_INT_*
+** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_*
 ** satisfy your needs.
 ** ===================================================================
 */
 
 /*
 @@ LUA_NUMBER is the floating-point type used by Lua.
-**
 @@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
 @@ over a floating number.
-**
+@@ l_mathlim(x) corrects limit name 'x' to the proper float type
+** by prefixing it with one of FLT/DBL/LDBL.
 @@ LUA_NUMBER_FRMLEN is the length modifier for writing floats.
 @@ LUA_NUMBER_FMT is the format for writing floats.
 @@ lua_number2str converts a float to a string.
-**
 @@ l_mathop allows the addition of an 'l' or 'f' to all math operations.
-**
+@@ l_floor takes the floor of a float.
 @@ lua_str2number converts a decimal numeric string to a number.
 */
 
-#if defined(LUA_REAL_FLOAT)		/* { single float */
+
+/* The following definitions are good for most cases here */
+
+#define l_floor(x)		(l_mathop(floor)(x))
+
+#define lua_number2str(s,sz,n)	l_sprintf((s), sz, LUA_NUMBER_FMT, (n))
+
+/*
+@@ lua_numbertointeger converts a float number to an integer, or
+** returns 0 if float is not within the range of a lua_Integer.
+** (The range comparisons are tricky because of rounding. The tests
+** here assume a two-complement representation, where MININTEGER always
+** has an exact representation as a float; MAXINTEGER may not have one,
+** and therefore its conversion to float may have an ill-defined value.)
+*/
+#define lua_numbertointeger(n,p) \
+  ((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \
+   (n) < -(LUA_NUMBER)(LUA_MININTEGER) && \
+      (*(p) = (LUA_INTEGER)(n), 1))
+
+
+/* now the variable definitions */
+
+#if LUA_FLOAT_TYPE == LUA_FLOAT_FLOAT		/* { single float */
 
 #define LUA_NUMBER	float
 
+#define l_mathlim(n)		(FLT_##n)
+
 #define LUAI_UACNUMBER	double
 
 #define LUA_NUMBER_FRMLEN	""
@@ -414,10 +455,12 @@
 #define lua_str2number(s,p)	strtof((s), (p))
 
 
-#elif defined(LUA_REAL_LONGDOUBLE)	/* }{ long double */
+#elif LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE	/* }{ long double */
 
 #define LUA_NUMBER	long double
 
+#define l_mathlim(n)		(LDBL_##n)
+
 #define LUAI_UACNUMBER	long double
 
 #define LUA_NUMBER_FRMLEN	"L"
@@ -427,10 +470,12 @@
 
 #define lua_str2number(s,p)	strtold((s), (p))
 
-#elif defined(LUA_REAL_DOUBLE)		/* }{ double */
+#elif LUA_FLOAT_TYPE == LUA_FLOAT_DOUBLE	/* }{ double */
 
 #define LUA_NUMBER	double
 
+#define l_mathlim(n)		(DBL_##n)
+
 #define LUAI_UACNUMBER	double
 
 #define LUA_NUMBER_FRMLEN	""
@@ -440,72 +485,13 @@
 
 #define lua_str2number(s,p)	strtod((s), (p))
 
-#else					/* }{ */
+#else						/* }{ */
 
-#error "numeric real type not defined"
+#error "numeric float type not defined"
 
 #endif					/* } */
 
 
-#define l_floor(x)		(l_mathop(floor)(x))
-
-#define lua_number2str(s,n)	sprintf((s), LUA_NUMBER_FMT, (n))
-
-
-/*
-@@ lua_numbertointeger converts a float number to an integer, or
-** returns 0 if float is not within the range of a lua_Integer.
-** (The range comparisons are tricky because of rounding. The tests
-** here assume a two-complement representation, where MININTEGER always
-** has an exact representation as a float; MAXINTEGER may not have one,
-** and therefore its conversion to float may have an ill-defined value.)
-*/
-#define lua_numbertointeger(n,p) \
-  ((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \
-   (n) < -(LUA_NUMBER)(LUA_MININTEGER) && \
-      (*(p) = (LUA_INTEGER)(n), 1))
-
-
-/*
-@@ The luai_num* macros define the primitive operations over numbers.
-** They should work for any size of floating numbers.
-*/
-
-/* the following operations need the math library */
-#if defined(lobject_c) || defined(lvm_c)
-#include <math.h>
-
-/* floor division (defined as 'floor(a/b)') */
-#define luai_numidiv(L,a,b)	((void)L, l_mathop(floor)(luai_numdiv(L,a,b)))
-
-/*
-** module: defined as 'a - floor(a/b)*b'; the previous definition gives
-** NaN when 'b' is huge, but the result should be 'a'. 'fmod' gives the
-** result of 'a - trunc(a/b)*b', and therefore must be corrected when
-** 'trunc(a/b) ~= floor(a/b)'. That happens when the division has a
-** non-integer negative result, which is equivalent to the test below
-*/
-#define luai_nummod(L,a,b,m)  \
-  { (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); }
-
-/* exponentiation */
-#define luai_numpow(L,a,b)	((void)L, l_mathop(pow)(a,b))
-
-#endif
-
-/* these are quite standard operations */
-#if defined(LUA_CORE)
-#define luai_numadd(L,a,b)	((a)+(b))
-#define luai_numsub(L,a,b)	((a)-(b))
-#define luai_nummul(L,a,b)	((a)*(b))
-#define luai_numdiv(L,a,b)	((a)/(b))
-#define luai_numunm(L,a)	(-(a))
-#define luai_numeq(a,b)		((a)==(b))
-#define luai_numlt(a,b)		((a)<(b))
-#define luai_numle(a,b)		((a)<=(b))
-#define luai_numisnan(a)	(!luai_numeq((a), (a)))
-#endif
-
 
 /*
 @@ LUA_INTEGER is the integer type used by Lua.
@@ -525,7 +511,7 @@
 /* The following definitions are good for most cases here */
 
 #define LUA_INTEGER_FMT		"%" LUA_INTEGER_FRMLEN "d"
-#define lua_integer2str(s,n)	sprintf((s), LUA_INTEGER_FMT, (n))
+#define lua_integer2str(s,sz,n)	l_sprintf((s), sz, LUA_INTEGER_FMT, (n))
 
 #define LUAI_UACINT		LUA_INTEGER
 
@@ -538,7 +524,7 @@
 
 /* now the variable definitions */
 
-#if defined(LUA_INT_INT)		/* { int */
+#if LUA_INT_TYPE == LUA_INT_INT		/* { int */
 
 #define LUA_INTEGER		int
 #define LUA_INTEGER_FRMLEN	""
@@ -546,7 +532,7 @@
 #define LUA_MAXINTEGER		INT_MAX
 #define LUA_MININTEGER		INT_MIN
 
-#elif defined(LUA_INT_LONG)	/* }{ long */
+#elif LUA_INT_TYPE == LUA_INT_LONG	/* }{ long */
 
 #define LUA_INTEGER		long
 #define LUA_INTEGER_FRMLEN	"l"
@@ -554,8 +540,9 @@
 #define LUA_MAXINTEGER		LONG_MAX
 #define LUA_MININTEGER		LONG_MIN
 
-#elif defined(LUA_INT_LONGLONG)	/* }{ long long */
+#elif LUA_INT_TYPE == LUA_INT_LONGLONG	/* }{ long long */
 
+/* use presence of macro LLONG_MAX as proxy for C99 compliance */
 #if defined(LLONG_MAX)		/* { */
 /* use ISO C99 stuff */
 
@@ -592,28 +579,40 @@
 
 /*
 ** {==================================================================
-** Dependencies with C99
+** Dependencies with C99 and other C details
 ** ===================================================================
 */
 
 /*
+@@ l_sprintf is equivalent to 'snprintf' or 'sprintf' in C89.
+** (All uses in Lua have only one format item.)
+*/
+#if !defined(LUA_USE_C89)
+#define l_sprintf(s,sz,f,i)	snprintf(s,sz,f,i)
+#else
+#define l_sprintf(s,sz,f,i)	((void)(sz), sprintf(s,f,i))
+#endif
+
+
+/*
 @@ lua_strx2number converts an hexadecimal numeric string to a number.
-** In C99, 'strtod' does both conversions. Otherwise, you can
+** In C99, 'strtod' does that conversion. Otherwise, you can
 ** leave 'lua_strx2number' undefined and Lua will provide its own
 ** implementation.
 */
 #if !defined(LUA_USE_C89)
-#define lua_strx2number(s,p)	lua_str2number(s,p)
+#define lua_strx2number(s,p)		lua_str2number(s,p)
 #endif
 
 
 /*
-@@ LUA_USE_AFORMAT allows '%a'/'%A' specifiers in 'string.format'
-** Enable it if the C function 'printf' supports these specifiers.
-** (C99 demands it and Windows also supports it.)
+@@ lua_number2strx converts a float to an hexadecimal numeric string. 
+** In C99, 'sprintf' (with format specifiers '%a'/'%A') does that.
+** Otherwise, you can leave 'lua_number2strx' undefined and Lua will
+** provide its own implementation.
 */
-#if !defined(LUA_USE_C89) || defined(LUA_USE_WINDOWS)
-#define LUA_USE_AFORMAT
+#if !defined(LUA_USE_C89)
+#define lua_number2strx(L,b,sz,f,n)	l_sprintf(b,sz,f,n)
 #endif
 
 
@@ -642,12 +641,50 @@
 #if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \
     __STDC_VERSION__ >= 199901L
 #include <stdint.h>
-#if defined (INTPTR_MAX)  /* even in C99 this type is optional */
+#if defined(INTPTR_MAX)  /* even in C99 this type is optional */
 #undef LUA_KCONTEXT
 #define LUA_KCONTEXT	intptr_t
 #endif
 #endif
 
+
+/*
+@@ lua_getlocaledecpoint gets the locale "radix character" (decimal point).
+** Change that if you do not want to use C locales. (Code using this
+** macro must include header 'locale.h'.)
+*/
+#if !defined(lua_getlocaledecpoint)
+#define lua_getlocaledecpoint()		(localeconv()->decimal_point[0])
+#endif
+
+/* }================================================================== */
+
+
+/*
+** {==================================================================
+** Language Variations
+** =====================================================================
+*/
+
+/*
+@@ LUA_NOCVTN2S/LUA_NOCVTS2N control how Lua performs some
+** coercions. Define LUA_NOCVTN2S to turn off automatic coercion from
+** numbers to strings. Define LUA_NOCVTS2N to turn off automatic
+** coercion from strings to numbers.
+*/
+/* #define LUA_NOCVTN2S */
+/* #define LUA_NOCVTS2N */
+
+
+/*
+@@ LUA_USE_APICHECK turns on several consistency checks on the C API.
+** Define it as a help when debugging C code.
+*/
+#if defined(LUA_USE_APICHECK)
+#include <assert.h>
+#define luai_apicheck(l,e)	assert(e)
+#endif
+
 /* }================================================================== */
 
 
@@ -671,9 +708,6 @@
 #define LUAI_MAXSTACK		15000
 #endif
 
-/* reserve some space for error handling */
-#define LUAI_FIRSTPSEUDOIDX	(-LUAI_MAXSTACK - 1000)
-
 
 /*
 @@ LUA_EXTRASPACE defines the size of a raw memory area associated with
@@ -692,19 +726,17 @@
 
 
 /*
-@@ LUAI_MAXSHORTLEN is the maximum length for short strings, that is,
-** strings that are internalized. (Cannot be smaller than reserved words
-** or tags for metamethods, as these strings must be internalized;
-** #("function") = 8, #("__newindex") = 10.)
-*/
-#define LUAI_MAXSHORTLEN        40
-
-
-/*
 @@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
-** CHANGE it if it uses too much C-stack space.
+** CHANGE it if it uses too much C-stack space. (For long double,
+** 'string.format("%.99f", 1e4932)' needs ~5030 bytes, so a
+** smaller buffer would force a memory allocation for each call to
+** 'string.format'.)
 */
-#define LUAL_BUFFERSIZE	((int)(0x80 * sizeof(void*) * sizeof(lua_Integer)))
+#if defined(LUA_FLOAT_LONGDOUBLE)
+#define LUAL_BUFFERSIZE		8192
+#else
+#define LUAL_BUFFERSIZE   ((int)(0x80 * sizeof(void*) * sizeof(lua_Integer)))
+#endif
 
 /* }================================================================== */
 

=== modified file 'src/third_party/eris/lundump.c'
--- src/third_party/eris/lundump.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lundump.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lundump.c,v 2.41 2014/11/02 19:19:04 roberto Exp $
+** $Id: lundump.c,v 2.44 2015/11/02 16:09:30 roberto Exp $
 ** load precompiled Lua chunks
 ** See Copyright Notice in lua.h
 */
@@ -32,7 +32,6 @@
 typedef struct {
   lua_State *L;
   ZIO *Z;
-  Mbuffer *b;
   const char *name;
 } LoadState;
 
@@ -92,10 +91,15 @@
     LoadVar(S, size);
   if (size == 0)
     return NULL;
-  else {
-    char *s = luaZ_openspace(S->L, S->b, --size);
-    LoadVector(S, s, size);
-    return luaS_newlstr(S->L, s, size);
+  else if (--size <= LUAI_MAXSHORTLEN) {  /* short string? */
+    char buff[LUAI_MAXSHORTLEN];
+    LoadVector(S, buff, size);
+    return luaS_newlstr(S->L, buff, size);
+  }
+  else {  /* long string */
+    TString *ts = luaS_createlngstrobj(S->L, size);
+    LoadVector(S, getstr(ts), size);  /* load directly in final place */
+    return ts;
   }
 }
 
@@ -251,8 +255,7 @@
 /*
 ** load precompiled chunk
 */
-LClosure *luaU_undump(lua_State *L, ZIO *Z, Mbuffer *buff,
-                      const char *name) {
+LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) {
   LoadState S;
   LClosure *cl;
   if (*name == '@' || *name == '=')
@@ -263,11 +266,10 @@
     S.name = name;
   S.L = L;
   S.Z = Z;
-  S.b = buff;
   checkHeader(&S);
   cl = luaF_newLclosure(L, LoadByte(&S));
   setclLvalue(L, L->top, cl);
-  incr_top(L);
+  luaD_inctop(L);
   cl->p = luaF_newproto(L);
   LoadFunction(&S, cl->p, NULL);
   lua_assert(cl->nupvalues == cl->p->sizeupvalues);

=== modified file 'src/third_party/eris/lundump.h'
--- src/third_party/eris/lundump.h	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lundump.h	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lundump.h,v 1.44 2014/06/19 18:27:20 roberto Exp $
+** $Id: lundump.h,v 1.45 2015/09/08 15:41:05 roberto Exp $
 ** load precompiled Lua chunks
 ** See Copyright Notice in lua.h
 */
@@ -23,8 +23,7 @@
 #define LUAC_FORMAT	0	/* this is the official format */
 
 /* load one chunk; from lundump.c */
-LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff,
-                                 const char* name);
+LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name);
 
 /* dump one chunk; from ldump.c */
 LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w,

=== modified file 'src/third_party/eris/lutf8lib.c'
--- src/third_party/eris/lutf8lib.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lutf8lib.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lutf8lib.c,v 1.13 2014/11/02 19:19:04 roberto Exp $
+** $Id: lutf8lib.c,v 1.15 2015/03/28 19:16:55 roberto Exp $
 ** Standard library for UTF-8 manipulation
 ** See Copyright Notice in lua.h
 */
@@ -11,6 +11,7 @@
 
 
 #include <assert.h>
+#include <limits.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -37,7 +38,7 @@
 ** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid.
 */
 static const char *utf8_decode (const char *o, int *val) {
-  static unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF};
+  static const unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF};
   const unsigned char *s = (const unsigned char *)o;
   unsigned int c = s[0];
   unsigned int res = 0;  /* final result */
@@ -106,9 +107,9 @@
   luaL_argcheck(L, posi >= 1, 2, "out of range");
   luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of range");
   if (posi > pose) return 0;  /* empty interval; return no values */
-  n = (int)(pose -  posi + 1);
-  if (posi + n <= pose)  /* (lua_Integer -> int) overflow? */
+  if (pose - posi >= INT_MAX)  /* (lua_Integer -> int) overflow? */
     return luaL_error(L, "string slice too long");
+  n = (int)(pose -  posi) + 1;
   luaL_checkstack(L, n, "string slice too long");
   n = 0;
   se = s + pose;
@@ -234,7 +235,7 @@
 #define UTF8PATT	"[\0-\x7F\xC2-\xF4][\x80-\xBF]*"
 
 
-static struct luaL_Reg funcs[] = {
+static const luaL_Reg funcs[] = {
   {"offset", byteoffset},
   {"codepoint", codepoint},
   {"char", utfchar},
@@ -248,7 +249,7 @@
 
 LUAMOD_API int luaopen_utf8 (lua_State *L) {
   luaL_newlib(L, funcs);
-  lua_pushliteral(L, UTF8PATT);
+  lua_pushlstring(L, UTF8PATT, sizeof(UTF8PATT)/sizeof(char) - 1);
   lua_setfield(L, -2, "charpattern");
   return 1;
 }

=== modified file 'src/third_party/eris/lvm.c'
--- src/third_party/eris/lvm.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lvm.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 2.232 2014/12/27 20:30:38 roberto Exp $
+** $Id: lvm.c,v 2.265 2015/11/23 11:30:45 roberto Exp $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -9,8 +9,9 @@
 
 #include "lprefix.h"
 
-
+#include <float.h>
 #include <limits.h>
+#include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -30,36 +31,38 @@
 #include "lvm.h"
 
 
-/*
-** You can define LUA_FLOORN2I if you want to convert floats to integers
-** by flooring them (instead of raising an error if they are not
-** integral values)
-*/
-#if !defined(LUA_FLOORN2I)
-#define LUA_FLOORN2I		0
-#endif
-
-
 /* limit for table tag-method chains (to avoid loops) */
 #define MAXTAGLOOP	2000
 
 
-/*
-** Similar to 'tonumber', but does not attempt to convert strings and
-** ensure correct precision (no extra bits). Used in comparisons.
-*/
-static int tofloat (const TValue *obj, lua_Number *n) {
-  if (ttisfloat(obj)) *n = fltvalue(obj);
-  else if (ttisinteger(obj)) {
-    volatile lua_Number x = cast_num(ivalue(obj));  /* avoid extra precision */
-    *n = x;
-  }
-  else {
-    *n = 0;  /* to avoid warnings */
-    return 0;
-  }
-  return 1;
-}
+
+/*
+** 'l_intfitsf' checks whether a given integer can be converted to a
+** float without rounding. Used in comparisons. Left undefined if
+** all integers fit in a float precisely.
+*/
+#if !defined(l_intfitsf)
+
+/* number of bits in the mantissa of a float */
+#define NBM		(l_mathlim(MANT_DIG))
+
+/*
+** Check whether some integers may not fit in a float, that is, whether
+** (maxinteger >> NBM) > 0 (that implies (1 << NBM) <= maxinteger).
+** (The shifts are done in parts to avoid shifting by more than the size
+** of an integer. In a worst case, NBM == 113 for long double and
+** sizeof(integer) == 32.)
+*/
+#if ((((LUA_MAXINTEGER >> (NBM / 4)) >> (NBM / 4)) >> (NBM / 4)) \
+	>> (NBM - (3 * (NBM / 4))))  >  0
+
+#define l_intfitsf(i)  \
+  (-((lua_Integer)1 << NBM) <= (i) && (i) <= ((lua_Integer)1 << NBM))
+
+#endif
+
+#endif
+
 
 
 /*
@@ -73,7 +76,7 @@
     return 1;
   }
   else if (cvt2num(obj) &&  /* string convertible to number? */
-            luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) {
+            luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) {
     *n = nvalue(&v);  /* convert result of 'luaO_str2num' to a float */
     return 1;
   }
@@ -88,7 +91,7 @@
 ** mode == 1: takes the floor of the number
 ** mode == 2: takes the ceil of the number
 */
-static int tointeger_aux (const TValue *obj, lua_Integer *p, int mode) {
+int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) {
   TValue v;
  again:
   if (ttisfloat(obj)) {
@@ -106,7 +109,7 @@
     return 1;
   }
   else if (cvt2num(obj) &&
-            luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) {
+            luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) {
     obj = &v;
     goto again;  /* convert result from 'luaO_str2num' to an integer */
   }
@@ -115,14 +118,6 @@
 
 
 /*
-** try to convert a value to an integer
-*/
-int luaV_tointeger_ (const TValue *obj, lua_Integer *p) {
-  return tointeger_aux(obj, p, LUA_FLOORN2I);
-}
-
-
-/*
 ** Try to convert a 'for' limit to an integer, preserving the
 ** semantics of the loop.
 ** (The following explanation assumes a non-negative step; it is valid
@@ -140,11 +135,11 @@
 static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step,
                      int *stopnow) {
   *stopnow = 0;  /* usually, let loops run */
-  if (!tointeger_aux(obj, p, (step < 0 ? 2 : 1))) {  /* not fit in integer? */
+  if (!luaV_tointeger(obj, p, (step < 0 ? 2 : 1))) {  /* not fit in integer? */
     lua_Number n;  /* try to convert to float */
     if (!tonumber(obj, &n)) /* cannot convert to float? */
       return 0;  /* not a number */
-    if (n > 0) {  /* if true, float is larger than max integer */
+    if (luai_numlt(0, n)) {  /* if true, float is larger than max integer */
       *p = LUA_MAXINTEGER;
       if (step < 0) *stopnow = 1;
     }
@@ -158,30 +153,28 @@
 
 
 /*
-** Main function for table access (invoking metamethods if needed).
-** Compute 'val = t[key]'
+** Complete a table access: if 't' is a table, 'tm' has its metamethod;
+** otherwise, 'tm' is NULL.
 */
-void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
+void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
+                      const TValue *tm) {
   int loop;  /* counter to avoid infinite loops */
+  lua_assert(tm != NULL || !ttistable(t));
   for (loop = 0; loop < MAXTAGLOOP; loop++) {
-    const TValue *tm;
-    if (ttistable(t)) {  /* 't' is a table? */
-      Table *h = hvalue(t);
-      const TValue *res = luaH_get(h, key); /* do a primitive get */
-      if (!ttisnil(res) ||  /* result is not nil? */
-          (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
-        setobj2s(L, val, res);  /* result is the raw get */
-        return;
-      }
-      /* else will try metamethod */
+    if (tm == NULL) {  /* no metamethod (from a table)? */
+      if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
+        luaG_typeerror(L, t, "index");  /* no metamethod */
     }
-    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
-      luaG_typeerror(L, t, "index");  /* no metamethod */
     if (ttisfunction(tm)) {  /* metamethod is a function */
-      luaT_callTM(L, tm, t, key, val, 1);
+      luaT_callTM(L, tm, t, key, val, 1);  /* call it */
       return;
     }
     t = tm;  /* else repeat access over 'tm' */
+    if (luaV_fastget(L,t,key,tm,luaH_get)) {  /* try fast track */
+      setobj2s(L, val, tm);  /* done */
+      return;
+    }
+    /* else repeat */
   }
   luaG_runerror(L, "gettable chain too long; possible loop");
 }
@@ -191,40 +184,42 @@
 ** Main function for table assignment (invoking metamethods if needed).
 ** Compute 't[key] = val'
 */
-void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
+void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
+                     StkId val, const TValue *oldval) {
   int loop;  /* counter to avoid infinite loops */
   for (loop = 0; loop < MAXTAGLOOP; loop++) {
     const TValue *tm;
-    if (ttistable(t)) {  /* 't' is a table? */
+    if (oldval != NULL) {
       Table *h = hvalue(t);
-      TValue *oldval = cast(TValue *, luaH_get(h, key));
-      /* if previous value is not nil, there must be a previous entry
-         in the table; a metamethod has no relevance */
-      if (!ttisnil(oldval) ||
-         /* previous value is nil; must check the metamethod */
-         ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL &&
+      lua_assert(ttisnil(oldval));
+      /* must check the metamethod */
+      if ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL &&
          /* no metamethod; is there a previous entry in the table? */
          (oldval != luaO_nilobject ||
          /* no previous entry; must create one. (The next test is
             always true; we only need the assignment.) */
-         (oldval = luaH_newkey(L, h, key), 1)))) {
+         (oldval = luaH_newkey(L, h, key), 1))) {
         /* no metamethod and (now) there is an entry with given key */
-        setobj2t(L, oldval, val);  /* assign new value to that entry */
+        setobj2t(L, cast(TValue *, oldval), val);
         invalidateTMcache(h);
         luaC_barrierback(L, h, val);
         return;
       }
       /* else will try the metamethod */
     }
-    else  /* not a table; check metamethod */
+    else {  /* not a table; check metamethod */
       if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
         luaG_typeerror(L, t, "index");
+    }
     /* try the metamethod */
     if (ttisfunction(tm)) {
       luaT_callTM(L, tm, t, key, val, 0);
       return;
     }
     t = tm;  /* else repeat assignment over 'tm' */
+    if (luaV_fastset(L, t, key, oldval, luaH_get, val))
+      return;  /* done */
+    /* else loop */
   }
   luaG_runerror(L, "settable chain too long; possible loop");
 }
@@ -239,9 +234,9 @@
 */
 static int l_strcmp (const TString *ls, const TString *rs) {
   const char *l = getstr(ls);
-  size_t ll = ls->len;
+  size_t ll = tsslen(ls);
   const char *r = getstr(rs);
-  size_t lr = rs->len;
+  size_t lr = tsslen(rs);
   for (;;) {  /* for each segment */
     int temp = strcoll(l, r);
     if (temp != 0)  /* not equal? */
@@ -261,15 +256,102 @@
 
 
 /*
+** Check whether integer 'i' is less than float 'f'. If 'i' has an
+** exact representation as a float ('l_intfitsf'), compare numbers as
+** floats. Otherwise, if 'f' is outside the range for integers, result
+** is trivial. Otherwise, compare them as integers. (When 'i' has no
+** float representation, either 'f' is "far away" from 'i' or 'f' has
+** no precision left for a fractional part; either way, how 'f' is
+** truncated is irrelevant.) When 'f' is NaN, comparisons must result
+** in false.
+*/
+static int LTintfloat (lua_Integer i, lua_Number f) {
+#if defined(l_intfitsf)
+  if (!l_intfitsf(i)) {
+    if (f >= -cast_num(LUA_MININTEGER))  /* -minint == maxint + 1 */
+      return 1;  /* f >= maxint + 1 > i */
+    else if (f > cast_num(LUA_MININTEGER))  /* minint < f <= maxint ? */
+      return (i < cast(lua_Integer, f));  /* compare them as integers */
+    else  /* f <= minint <= i (or 'f' is NaN)  -->  not(i < f) */
+      return 0;
+  }
+#endif
+  return luai_numlt(cast_num(i), f);  /* compare them as floats */
+}
+
+
+/*
+** Check whether integer 'i' is less than or equal to float 'f'.
+** See comments on previous function.
+*/
+static int LEintfloat (lua_Integer i, lua_Number f) {
+#if defined(l_intfitsf)
+  if (!l_intfitsf(i)) {
+    if (f >= -cast_num(LUA_MININTEGER))  /* -minint == maxint + 1 */
+      return 1;  /* f >= maxint + 1 > i */
+    else if (f >= cast_num(LUA_MININTEGER))  /* minint <= f <= maxint ? */
+      return (i <= cast(lua_Integer, f));  /* compare them as integers */
+    else  /* f < minint <= i (or 'f' is NaN)  -->  not(i <= f) */
+      return 0;
+  }
+#endif
+  return luai_numle(cast_num(i), f);  /* compare them as floats */
+}
+
+
+/*
+** Return 'l < r', for numbers.
+*/
+static int LTnum (const TValue *l, const TValue *r) {
+  if (ttisinteger(l)) {
+    lua_Integer li = ivalue(l);
+    if (ttisinteger(r))
+      return li < ivalue(r);  /* both are integers */
+    else  /* 'l' is int and 'r' is float */
+      return LTintfloat(li, fltvalue(r));  /* l < r ? */
+  }
+  else {
+    lua_Number lf = fltvalue(l);  /* 'l' must be float */
+    if (ttisfloat(r))
+      return luai_numlt(lf, fltvalue(r));  /* both are float */
+    else if (luai_numisnan(lf))  /* 'r' is int and 'l' is float */
+      return 0;  /* NaN < i is always false */
+    else  /* without NaN, (l < r)  <-->  not(r <= l) */
+      return !LEintfloat(ivalue(r), lf);  /* not (r <= l) ? */
+  }
+}
+
+
+/*
+** Return 'l <= r', for numbers.
+*/
+static int LEnum (const TValue *l, const TValue *r) {
+  if (ttisinteger(l)) {
+    lua_Integer li = ivalue(l);
+    if (ttisinteger(r))
+      return li <= ivalue(r);  /* both are integers */
+    else  /* 'l' is int and 'r' is float */
+      return LEintfloat(li, fltvalue(r));  /* l <= r ? */
+  }
+  else {
+    lua_Number lf = fltvalue(l);  /* 'l' must be float */
+    if (ttisfloat(r))
+      return luai_numle(lf, fltvalue(r));  /* both are float */
+    else if (luai_numisnan(lf))  /* 'r' is int and 'l' is float */
+      return 0;  /*  NaN <= i is always false */
+    else  /* without NaN, (l <= r)  <-->  not(r < l) */
+      return !LTintfloat(ivalue(r), lf);  /* not (r < l) ? */
+  }
+}
+
+
+/*
 ** Main operation less than; return 'l < r'.
 */
 int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
   int res;
-  lua_Number nl, nr;
-  if (ttisinteger(l) && ttisinteger(r))  /* both operands are integers? */
-    return (ivalue(l) < ivalue(r));
-  else if (tofloat(l, &nl) && tofloat(r, &nr))  /* both are numbers? */
-    return luai_numlt(nl, nr);
+  if (ttisnumber(l) && ttisnumber(r))  /* both operands are numbers? */
+    return LTnum(l, r);
   else if (ttisstring(l) && ttisstring(r))  /* both are strings? */
     return l_strcmp(tsvalue(l), tsvalue(r)) < 0;
   else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0)  /* no metamethod? */
@@ -279,27 +361,34 @@
 
 
 /*
-** Main operation less than or equal to; return 'l <= r'.
+** Main operation less than or equal to; return 'l <= r'. If it needs
+** a metamethod and there is no '__le', try '__lt', based on
+** l <= r iff !(r < l) (assuming a total order). If the metamethod
+** yields during this substitution, the continuation has to know
+** about it (to negate the result of r<l); bit CIST_LEQ in the call
+** status keeps that information.
 */
 int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) {
   int res;
-  lua_Number nl, nr;
-  if (ttisinteger(l) && ttisinteger(r))  /* both operands are integers? */
-    return (ivalue(l) <= ivalue(r));
-  else if (tofloat(l, &nl) && tofloat(r, &nr))  /* both are numbers? */
-    return luai_numle(nl, nr);
+  if (ttisnumber(l) && ttisnumber(r))  /* both operands are numbers? */
+    return LEnum(l, r);
   else if (ttisstring(l) && ttisstring(r))  /* both are strings? */
     return l_strcmp(tsvalue(l), tsvalue(r)) <= 0;
-  else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0)  /* first try 'le' */
+  else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0)  /* try 'le' */
     return res;
-  else if ((res = luaT_callorderTM(L, r, l, TM_LT)) < 0)  /* else try 'lt' */
-    luaG_ordererror(L, l, r);
-  return !res;
+  else {  /* try 'lt': */
+    L->ci->callstatus |= CIST_LEQ;  /* mark it is doing 'lt' for 'le' */
+    res = luaT_callorderTM(L, r, l, TM_LT);
+    L->ci->callstatus ^= CIST_LEQ;  /* clear mark */
+    if (res < 0)
+      luaG_ordererror(L, l, r);
+    return !res;  /* result is negated */
+  }
 }
 
 
 /*
-** Main operation for equality of Lua values; return 't1 == t2'. 
+** Main operation for equality of Lua values; return 't1 == t2'.
 ** L == NULL means raw equality (no metamethods)
 */
 int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
@@ -308,10 +397,8 @@
     if (ttnov(t1) != ttnov(t2) || ttnov(t1) != LUA_TNUMBER)
       return 0;  /* only numbers can be equal with different variants */
     else {  /* two numbers with different variants */
-      lua_Number n1, n2;  /* compare them as floats */
-      lua_assert(ttisnumber(t1) && ttisnumber(t2));
-      cast_void(tofloat(t1, &n1)); cast_void(tofloat(t2, &n2));
-      return luai_numeq(n1, n2);
+      lua_Integer i1, i2;  /* compare them as integers */
+      return (tointeger(t1, &i1) && tointeger(t2, &i2) && i1 == i2);
     }
   }
   /* values have same type and same variant */
@@ -354,6 +441,19 @@
 #define tostring(L,o)  \
 	(ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1)))
 
+#define isemptystr(o)	(ttisshrstring(o) && tsvalue(o)->shrlen == 0)
+
+/* copy strings in stack from top - n up to top - 1 to buffer */
+static void copy2buff (StkId top, int n, char *buff) {
+  size_t tl = 0;  /* size already copied */
+  do {
+    size_t l = vslen(top - n);  /* length of string being copied */
+    memcpy(buff + tl, svalue(top - n), l * sizeof(char));
+    tl += l;
+  } while (--n > 0);
+}
+
+
 /*
 ** Main operation for concatenation: concat 'total' values in the stack,
 ** from 'L->top - total' up to 'L->top - 1'.
@@ -365,32 +465,32 @@
     int n = 2;  /* number of elements handled in this pass (at least 2) */
     if (!(ttisstring(top-2) || cvt2str(top-2)) || !tostring(L, top-1))
       luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT);
-    else if (tsvalue(top-1)->len == 0)  /* second operand is empty? */
+    else if (isemptystr(top - 1))  /* second operand is empty? */
       cast_void(tostring(L, top - 2));  /* result is first operand */
-    else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) {
+    else if (isemptystr(top - 2)) {  /* first operand is an empty string? */
       setobjs2s(L, top - 2, top - 1);  /* result is second op. */
     }
     else {
       /* at least two non-empty string values; get as many as possible */
-      size_t tl = tsvalue(top-1)->len;
-      char *buffer;
-      int i;
-      /* collect total length */
-      for (i = 1; i < total && tostring(L, top-i-1); i++) {
-        size_t l = tsvalue(top-i-1)->len;
+      size_t tl = vslen(top - 1);
+      TString *ts;
+      /* collect total length and number of strings */
+      for (n = 1; n < total && tostring(L, top - n - 1); n++) {
+        size_t l = vslen(top - n - 1);
         if (l >= (MAX_SIZE/sizeof(char)) - tl)
           luaG_runerror(L, "string length overflow");
         tl += l;
       }
-      buffer = luaZ_openspace(L, &G(L)->buff, tl);
-      tl = 0;
-      n = i;
-      do {  /* copy all strings to buffer */
-        size_t l = tsvalue(top-i)->len;
-        memcpy(buffer+tl, svalue(top-i), l * sizeof(char));
-        tl += l;
-      } while (--i > 0);
-      setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));  /* create result */
+      if (tl <= LUAI_MAXSHORTLEN) {  /* is result a short string? */
+        char buff[LUAI_MAXSHORTLEN];
+        copy2buff(top, n, buff);  /* copy strings to buffer */
+        ts = luaS_newlstr(L, buff, tl);
+      }
+      else {  /* long string; copy strings directly to final result */
+        ts = luaS_createlngstrobj(L, tl);
+        copy2buff(top, n, getstr(ts));
+      }
+      setsvalue2s(L, top - n, ts);  /* create result */
     }
     total -= n-1;  /* got 'n' strings to create 1 new */
     L->top -= n-1;  /* popped 'n' strings and pushed one */
@@ -403,7 +503,7 @@
 */
 void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
   const TValue *tm;
-  switch (ttnov(rb)) {
+  switch (ttype(rb)) {
     case LUA_TTABLE: {
       Table *h = hvalue(rb);
       tm = fasttm(L, h->metatable, TM_LEN);
@@ -411,8 +511,12 @@
       setivalue(ra, luaH_getn(h));  /* else primitive len */
       return;
     }
-    case LUA_TSTRING: {
-      setivalue(ra, tsvalue(rb)->len);
+    case LUA_TSHRSTR: {
+      setivalue(ra, tsvalue(rb)->shrlen);
+      return;
+    }
+    case LUA_TLNGSTR: {
+      setivalue(ra, tsvalue(rb)->u.lnglen);
       return;
     }
     default: {  /* try metamethod */
@@ -448,7 +552,7 @@
 
 
 /*
-** Integer modulus; return 'm % n'. (Assume that C '%' with 
+** Integer modulus; return 'm % n'. (Assume that C '%' with
 ** negative operands follows C99 behavior. See previous comment
 ** about luaV_div.)
 */
@@ -553,11 +657,11 @@
     case OP_LE: case OP_LT: case OP_EQ: {
       int res = !l_isfalse(L->top - 1);
       L->top--;
-      /* metamethod should not be called when operand is K */
-      lua_assert(!ISK(GETARG_B(inst)));
-      if (op == OP_LE &&  /* "<=" using "<" instead? */
-          ttisnil(luaT_gettmbyobj(L, base + GETARG_B(inst), TM_LE)))
-        res = !res;  /* invert result */
+      if (ci->callstatus & CIST_LEQ) {  /* "<=" using "<" instead? */
+        lua_assert(op == OP_LE);
+        ci->callstatus ^= CIST_LEQ;  /* clear mark */
+        res = !res;  /* negate result */
+      }
       lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP);
       if (res != GETARG_A(inst))  /* condition failed? */
         ci->u.l.savedpc++;  /* skip jump instruction */
@@ -607,27 +711,20 @@
 ** some macros for common tasks in 'luaV_execute'
 */
 
-#if !defined luai_runtimecheck
-#define luai_runtimecheck(L, c)		/* void */
-#endif
-
 
 #define RA(i)	(base+GETARG_A(i))
-/* to be used after possible stack reallocation */
 #define RB(i)	check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i))
 #define RC(i)	check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))
 #define RKB(i)	check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \
 	ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i))
 #define RKC(i)	check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \
 	ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i))
-#define KBx(i)  \
-  (k + (GETARG_Bx(i) != 0 ? GETARG_Bx(i) - 1 : GETARG_Ax(*ci->u.l.savedpc++)))
 
 
 /* execute a jump instruction */
 #define dojump(ci,i,e) \
   { int a = GETARG_A(i); \
-    if (a > 0) luaF_close(L, ci->u.l.base + a - 1); \
+    if (a != 0) luaF_close(L, ci->u.l.base + a - 1); \
     ci->u.l.savedpc += GETARG_sBx(i) + e; }
 
 /* for test instructions, execute the jump instruction that follows it */
@@ -637,34 +734,49 @@
 #define Protect(x)	{ {x;}; base = ci->u.l.base; }
 
 #define checkGC(L,c)  \
-  Protect( luaC_condGC(L,{L->top = (c);  /* limit of live values */ \
-                          luaC_step(L); \
-                          L->top = ci->top;})  /* restore top */ \
-           luai_threadyield(L); )
+	{ luaC_condGC(L, L->top = (c),  /* limit of live values */ \
+                         Protect(L->top = ci->top));  /* restore top */ \
+           luai_threadyield(L); }
 
 
 #define vmdispatch(o)	switch(o)
 #define vmcase(l)	case l:
 #define vmbreak		break
 
+
+/*
+** copy of 'luaV_gettable', but protecting call to potential metamethod
+** (which can reallocate the stack)
+*/
+#define gettableProtected(L,t,k,v)  { const TValue *aux; \
+  if (luaV_fastget(L,t,k,aux,luaH_get)) { setobj2s(L, v, aux); } \
+  else Protect(luaV_finishget(L,t,k,v,aux)); }
+
+
+/* same for 'luaV_settable' */
+#define settableProtected(L,t,k,v) { const TValue *slot; \
+  if (!luaV_fastset(L,t,k,slot,luaH_get,v)) \
+    Protect(luaV_finishset(L,t,k,v,slot)); }
+
+
+
 void luaV_execute (lua_State *L) {
   CallInfo *ci = L->ci;
   LClosure *cl;
   TValue *k;
   StkId base;
+  ci->callstatus |= CIST_FRESH;  /* fresh invocation of 'luaV_execute" */
  newframe:  /* reentry point when frame changes (call/return) */
   lua_assert(ci == L->ci);
-  cl = clLvalue(ci->func);
-  k = cl->p->k;
-  base = ci->u.l.base;
+  cl = clLvalue(ci->func);  /* local reference to function's closure */
+  k = cl->p->k;  /* local reference to function's constant table */
+  base = ci->u.l.base;  /* local copy of function's base */
   /* main loop of interpreter */
   for (;;) {
     Instruction i = *(ci->u.l.savedpc++);
     StkId ra;
-    if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
-        (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
+    if (L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT))
       Protect(luaG_traceexec(L));
-    }
     /* WARNING: several calls may realloc the stack and invalidate 'ra' */
     ra = RA(i);
     lua_assert(base == ci->u.l.base);
@@ -704,17 +816,22 @@
         vmbreak;
       }
       vmcase(OP_GETTABUP) {
-        int b = GETARG_B(i);
-        Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra));
+        TValue *upval = cl->upvals[GETARG_B(i)]->v;
+        TValue *rc = RKC(i);
+        gettableProtected(L, upval, rc, ra);
         vmbreak;
       }
       vmcase(OP_GETTABLE) {
-        Protect(luaV_gettable(L, RB(i), RKC(i), ra));
+        StkId rb = RB(i);
+        TValue *rc = RKC(i);
+        gettableProtected(L, rb, rc, ra);
         vmbreak;
       }
       vmcase(OP_SETTABUP) {
-        int a = GETARG_A(i);
-        Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i)));
+        TValue *upval = cl->upvals[GETARG_A(i)]->v;
+        TValue *rb = RKB(i);
+        TValue *rc = RKC(i);
+        settableProtected(L, upval, rb, rc);
         vmbreak;
       }
       vmcase(OP_SETUPVAL) {
@@ -724,7 +841,9 @@
         vmbreak;
       }
       vmcase(OP_SETTABLE) {
-        Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
+        TValue *rb = RKB(i);
+        TValue *rc = RKC(i);
+        settableProtected(L, ra, rb, rc);
         vmbreak;
       }
       vmcase(OP_NEWTABLE) {
@@ -738,12 +857,18 @@
         vmbreak;
       }
       vmcase(OP_SELF) {
+        const TValue *aux;
         StkId rb = RB(i);
-        setobjs2s(L, ra+1, rb);
-        Protect(luaV_gettable(L, rb, RKC(i), ra));
+        TValue *rc = RKC(i);
+        TString *key = tsvalue(rc);  /* key must be a string */
+        setobjs2s(L, ra + 1, rb);
+        if (luaV_fastget(L, rb, key, aux, luaH_getstr)) {
+          setobj2s(L, ra, aux);
+        }
+        else Protect(luaV_finishget(L, rb, rc, ra, aux));
         vmbreak;
       }
-      vmcase(OP_ADD) { 
+      vmcase(OP_ADD) {
         TValue *rb = RKB(i);
         TValue *rc = RKC(i);
         lua_Number nb; lua_Number nc;
@@ -927,8 +1052,8 @@
         StkId rb;
         L->top = base + c + 1;  /* mark the end of concat operands */
         Protect(luaV_concat(L, c - b + 1));
-        ra = RA(i);  /* 'luav_concat' may invoke TMs and move the stack */
-        rb = b + base;
+        ra = RA(i);  /* 'luaV_concat' may invoke TMs and move the stack */
+        rb = base + b;
         setobjs2s(L, ra, rb);
         checkGC(L, (ra >= rb ? ra + 1 : rb));
         L->top = ci->top;  /* restore top */
@@ -942,7 +1067,7 @@
         TValue *rb = RKB(i);
         TValue *rc = RKC(i);
         Protect(
-          if (cast_int(luaV_equalobj(L, rb, rc)) != GETARG_A(i))
+          if (luaV_equalobj(L, rb, rc) != GETARG_A(i))
             ci->u.l.savedpc++;
           else
             donextjump(ci);
@@ -989,12 +1114,12 @@
         int nresults = GETARG_C(i) - 1;
         if (b != 0) L->top = ra+b;  /* else previous instruction set top */
         if (luaD_precall(L, ra, nresults)) {  /* C function? */
-          if (nresults >= 0) L->top = ci->top;  /* adjust results */
-          base = ci->u.l.base;
+          if (nresults >= 0)
+            L->top = ci->top;  /* adjust results */
+          Protect((void)0);  /* update 'base' */
         }
         else {  /* Lua function */
           ci = L->ci;
-          ci->callstatus |= CIST_REENTRY;
           goto newframe;  /* restart luaV_execute over new Lua function */
         }
         vmbreak;
@@ -1003,8 +1128,9 @@
         int b = GETARG_B(i);
         if (b != 0) L->top = ra+b;  /* else previous instruction set top */
         lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
-        if (luaD_precall(L, ra, LUA_MULTRET))  /* C function? */
-          base = ci->u.l.base;
+        if (luaD_precall(L, ra, LUA_MULTRET)) {  /* C function? */
+          Protect((void)0);  /* update 'base' */
+        }
         else {
           /* tail call: put called frame (n) in place of caller one (o) */
           CallInfo *nci = L->ci;  /* called frame */
@@ -1031,10 +1157,9 @@
       }
       vmcase(OP_RETURN) {
         int b = GETARG_B(i);
-        if (b != 0) L->top = ra+b-1;
         if (cl->p->sizep > 0) luaF_close(L, base);
-        b = luaD_poscall(L, ra);
-        if (!(ci->callstatus & CIST_REENTRY))  /* 'ci' still the called one */
+        b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra)));
+        if (ci->callstatus & CIST_FRESH)  /* local 'ci' still from callee */
           return;  /* external invocation: return */
         else {  /* invocation via reentry: continue execution */
           ci = L->ci;
@@ -1047,11 +1172,11 @@
       vmcase(OP_FORLOOP) {
         if (ttisinteger(ra)) {  /* integer loop? */
           lua_Integer step = ivalue(ra + 2);
-          lua_Integer idx = ivalue(ra) + step; /* increment index */
+          lua_Integer idx = intop(+, ivalue(ra), step); /* increment index */
           lua_Integer limit = ivalue(ra + 1);
           if ((0 < step) ? (idx <= limit) : (limit <= idx)) {
             ci->u.l.savedpc += GETARG_sBx(i);  /* jump back */
-            setivalue(ra, idx);  /* update internal index... */
+            chgivalue(ra, idx);  /* update internal index... */
             setivalue(ra + 3, idx);  /* ...and external index */
           }
         }
@@ -1062,7 +1187,7 @@
           if (luai_numlt(0, step) ? luai_numle(idx, limit)
                                   : luai_numle(limit, idx)) {
             ci->u.l.savedpc += GETARG_sBx(i);  /* jump back */
-            setfltvalue(ra, idx);  /* update internal index... */
+            chgfltvalue(ra, idx);  /* update internal index... */
             setfltvalue(ra + 3, idx);  /* ...and external index */
           }
         }
@@ -1079,7 +1204,7 @@
           /* all values are integer */
           lua_Integer initv = (stopnow ? 0 : ivalue(init));
           setivalue(plimit, ilimit);
-          setivalue(init, initv - ivalue(pstep));
+          setivalue(init, intop(-, initv, ivalue(pstep)));
         }
         else {  /* try making all values floats */
           lua_Number ninit; lua_Number nlimit; lua_Number nstep;
@@ -1102,7 +1227,7 @@
         setobjs2s(L, cb+1, ra+1);
         setobjs2s(L, cb, ra);
         L->top = cb + 3;  /* func. + 2 args (state and index) */
-        Protect(luaD_call(L, cb, GETARG_C(i), 1));
+        Protect(luaD_call(L, cb, GETARG_C(i)));
         L->top = ci->top;
         i = *(ci->u.l.savedpc++);  /* go to next instruction */
         ra = RA(i);
@@ -1127,11 +1252,10 @@
           lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG);
           c = GETARG_Ax(*ci->u.l.savedpc++);
         }
-        luai_runtimecheck(L, ttistable(ra));
         h = hvalue(ra);
         last = ((c-1)*LFIELDS_PER_FLUSH) + n;
         if (last > h->sizearray)  /* needs more space? */
-          luaH_resizearray(L, h, last);  /* pre-allocate it at once */
+          luaH_resizearray(L, h, last);  /* preallocate it at once */
         for (; n > 0; n--) {
           TValue *val = ra+n;
           luaH_setint(L, h, last--, val);
@@ -1151,23 +1275,21 @@
         vmbreak;
       }
       vmcase(OP_VARARG) {
-        int b = GETARG_B(i) - 1;
+        int b = GETARG_B(i) - 1;  /* required results */
         int j;
         int n = cast_int(base - ci->func) - cl->p->numparams - 1;
+        if (n < 0)  /* less arguments than parameters? */
+          n = 0;  /* no vararg arguments */
         if (b < 0) {  /* B == 0? */
           b = n;  /* get all var. arguments */
           Protect(luaD_checkstack(L, n));
           ra = RA(i);  /* previous call may change the stack */
           L->top = ra + n;
         }
-        for (j = 0; j < b; j++) {
-          if (j < n) {
-            setobjs2s(L, ra + j, base - n + j);
-          }
-          else {
-            setnilvalue(ra + j);
-          }
-        }
+        for (j = 0; j < b && j < n; j++)
+          setobjs2s(L, ra + j, base - n + j);
+        for (; j < b; j++)  /* complete required results with nil */
+          setnilvalue(ra + j);
         vmbreak;
       }
       vmcase(OP_EXTRAARG) {

=== modified file 'src/third_party/eris/lvm.h'
--- src/third_party/eris/lvm.h	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lvm.h	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.h,v 2.34 2014/08/01 17:24:02 roberto Exp $
+** $Id: lvm.h,v 2.39 2015/09/09 13:44:07 roberto Exp $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -27,26 +27,82 @@
 #endif
 
 
+/*
+** You can define LUA_FLOORN2I if you want to convert floats to integers
+** by flooring them (instead of raising an error if they are not
+** integral values)
+*/
+#if !defined(LUA_FLOORN2I)
+#define LUA_FLOORN2I		0
+#endif
+
+
 #define tonumber(o,n) \
 	(ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n))
 
 #define tointeger(o,i) \
-	(ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger_(o,i))
+    (ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger(o,i,LUA_FLOORN2I))
 
 #define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2))
 
 #define luaV_rawequalobj(t1,t2)		luaV_equalobj(NULL,t1,t2)
 
 
+/*
+** fast track for 'gettable': 1 means 'aux' points to resulted value;
+** 0 means 'aux' is metamethod (if 't' is a table) or NULL. 'f' is
+** the raw get function to use.
+*/
+#define luaV_fastget(L,t,k,aux,f) \
+  (!ttistable(t)  \
+   ? (aux = NULL, 0)  /* not a table; 'aux' is NULL and result is 0 */  \
+   : (aux = f(hvalue(t), k),  /* else, do raw access */  \
+      !ttisnil(aux) ? 1  /* result not nil? 'aux' has it */  \
+      : (aux = fasttm(L, hvalue(t)->metatable, TM_INDEX),  /* get metamethod */\
+         aux != NULL  ? 0  /* has metamethod? must call it */  \
+         : (aux = luaO_nilobject, 1))))  /* else, final result is nil */
+
+/*
+** standard implementation for 'gettable'
+*/
+#define luaV_gettable(L,t,k,v) { const TValue *aux; \
+  if (luaV_fastget(L,t,k,aux,luaH_get)) { setobj2s(L, v, aux); } \
+  else luaV_finishget(L,t,k,v,aux); }
+
+
+/*
+** Fast track for set table. If 't' is a table and 't[k]' is not nil,
+** call GC barrier, do a raw 't[k]=v', and return true; otherwise,
+** return false with 'slot' equal to NULL (if 't' is not a table) or
+** 'nil'. (This is needed by 'luaV_finishget'.) Note that, if the macro
+** returns true, there is no need to 'invalidateTMcache', because the
+** call is not creating a new entry.
+*/
+#define luaV_fastset(L,t,k,slot,f,v) \
+  (!ttistable(t) \
+   ? (slot = NULL, 0) \
+   : (slot = f(hvalue(t), k), \
+     ttisnil(slot) ? 0 \
+     : (luaC_barrierback(L, hvalue(t), v), \
+        setobj2t(L, cast(TValue *,slot), v), \
+        1)))
+
+
+#define luaV_settable(L,t,k,v) { const TValue *slot; \
+  if (!luaV_fastset(L,t,k,slot,luaH_get,v)) \
+    luaV_finishset(L,t,k,v,slot); }
+  
+
+
 LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2);
 LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
 LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r);
 LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n);
-LUAI_FUNC int luaV_tointeger_ (const TValue *obj, lua_Integer *p);
-LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,
-                                            StkId val);
-LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,
-                                            StkId val);
+LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode);
+LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key,
+                               StkId val, const TValue *tm);
+LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
+                               StkId val, const TValue *oldval);
 LUAI_FUNC void luaV_finishOp (lua_State *L);
 LUAI_FUNC void luaV_execute (lua_State *L);
 LUAI_FUNC void luaV_concat (lua_State *L, int total);

=== modified file 'src/third_party/eris/lzio.c'
--- src/third_party/eris/lzio.c	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lzio.c	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lzio.c,v 1.36 2014/11/02 19:19:04 roberto Exp $
+** $Id: lzio.c,v 1.37 2015/09/08 15:41:05 roberto Exp $
 ** Buffered streams
 ** See Copyright Notice in lua.h
 */
@@ -66,13 +66,3 @@
   return 0;
 }
 
-/* ------------------------------------------------------------------------ */
-char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) {
-  if (n > buff->buffsize) {
-    if (n < LUA_MINBUFFER) n = LUA_MINBUFFER;
-    luaZ_resizebuffer(L, buff, n);
-  }
-  return buff->buffer;
-}
-
-

=== modified file 'src/third_party/eris/lzio.h'
--- src/third_party/eris/lzio.h	2016-04-08 18:00:30 +0000
+++ src/third_party/eris/lzio.h	2016-04-23 09:01:53 +0000
@@ -1,5 +1,5 @@
 /*
-** $Id: lzio.h,v 1.30 2014/12/19 17:26:14 roberto Exp $
+** $Id: lzio.h,v 1.31 2015/09/08 15:41:05 roberto Exp $
 ** Buffered streams
 ** See Copyright Notice in lua.h
 */
@@ -44,7 +44,6 @@
 #define luaZ_freebuffer(L, buff)	luaZ_resizebuffer(L, buff, 0)
 
 
-LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);
 LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader,
                                         void *data);
 LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n);	/* read next n bytes */


Follow ups