Revamp around 'L->nCcalls' count

The field 'L->nCcalls' now counts downwards, so that the C-stack
limits do not depend on the stack size.
diff --git a/ldo.c b/ldo.c
index e7e76a6..0ad3120 100644
--- a/ldo.c
+++ b/ldo.c
@@ -139,9 +139,8 @@
 
 
 int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
-  l_uint32 oldnCcalls = L->nCcalls - L->nci;
+  l_uint32 oldnCcalls = L->nCcalls + L->nci;
   struct lua_longjmp lj;
-  lua_assert(L->nCcalls >= L->nci);
   lj.status = LUA_OK;
   lj.previous = L->errorJmp;  /* chain new error handler */
   L->errorJmp = &lj;
@@ -149,7 +148,7 @@
     (*f)(L, ud);
   );
   L->errorJmp = lj.previous;  /* restore old error handler */
-  L->nCcalls = oldnCcalls + L->nci;
+  L->nCcalls = oldnCcalls - L->nci;
   return lj.status;
 }
 
@@ -521,7 +520,7 @@
 */
 void luaD_callnoyield (lua_State *L, StkId func, int nResults) {
   incXCcalls(L);
-  if (getCcalls(L) >= LUAI_MAXCSTACK)  /* possible stack overflow? */
+  if (getCcalls(L) <= CSTACKERR)  /* possible stack overflow? */
     luaE_freeCI(L);
   luaD_call(L, func, nResults);
   decXCcalls(L);
@@ -672,10 +671,10 @@
   else if (L->status != LUA_YIELD)  /* ended with errors? */
     return resume_error(L, "cannot resume dead coroutine", nargs);
   if (from == NULL)
-    L->nCcalls = 1;
+    L->nCcalls = LUAI_MAXCSTACK;
   else  /* correct 'nCcalls' for this thread */
-    L->nCcalls = getCcalls(from) - from->nci + L->nci + CSTACKCF;
-  if (L->nCcalls >= LUAI_MAXCSTACK)
+    L->nCcalls = getCcalls(from) + from->nci - L->nci - CSTACKCF;
+  if (L->nCcalls <= CSTACKERR)
     return resume_error(L, "C stack overflow", nargs);
   luai_userstateresume(L, nargs);
   api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
diff --git a/lstate.c b/lstate.c
index 387cd36..296cec2 100644
--- a/lstate.c
+++ b/lstate.c
@@ -97,35 +97,34 @@
 
 
 /*
-** Increment count of "C calls" and check for overflows. In case of
+** Decrement count of "C calls" and check for overflows. In case of
 ** a stack overflow, check appropriate error ("regular" overflow or
-** overflow while handling stack overflow).
-** If 'nCcalls' is larger than LUAI_MAXCSTACK but smaller than
-** LUAI_MAXCSTACK + CSTACKCF (plus 2 to avoid by-one errors), it means
-** it has just entered the "overflow zone", so the function raises an
-** overflow error.
-** If 'nCcalls' is larger than LUAI_MAXCSTACK + CSTACKCF + 2
-** (which means it is already handling an overflow) but smaller than
-** 9/8 of LUAI_MAXCSTACK, does not report an error (to allow message
-** handling to work).
-** Otherwise, report a stack overflow while handling a stack overflow
-** (probably caused by a repeating error in the message handling
-** function).
+** overflow while handling stack overflow).  If 'nCcalls' is smaller
+** than CSTACKERR but larger than CSTACKMARK, it means it has just
+** entered the "overflow zone", so the function raises an overflow
+** error.  If 'nCcalls' is smaller than CSTACKMARK (which means it is
+** already handling an overflow) but larger than CSTACKERRMARK, does
+** not report an error (to allow message handling to work). Otherwise,
+** report a stack overflow while handling a stack overflow (probably
+** caused by a repeating error in the message handling function).
 */
+
 void luaE_enterCcall (lua_State *L) {
   int ncalls = getCcalls(L);
-  L->nCcalls++;
-  if (ncalls >= LUAI_MAXCSTACK) {  /* possible overflow? */
+  L->nCcalls--;
+  if (ncalls <= CSTACKERR) {  /* possible overflow? */
     luaE_freeCI(L);  /* release unused CIs */
     ncalls = getCcalls(L);  /* update call count */
-    if (ncalls >= LUAI_MAXCSTACK) {  /* still overflow? */
-      if (ncalls <= LUAI_MAXCSTACK + CSTACKCF + 2) {
-        /* no error before increments; raise the error now */
-        L->nCcalls += (CSTACKCF + 4);  /* avoid raising it again */
-        luaG_runerror(L, "C stack overflow");
-      }
-      else if (ncalls >= (LUAI_MAXCSTACK + (LUAI_MAXCSTACK >> 3)))
+    if (ncalls <= CSTACKERR) {  /* still overflow? */
+      if (ncalls <= CSTACKERRMARK)  /* below error-handling zone? */
         luaD_throw(L, LUA_ERRERR);  /* error while handling stack error */
+      else if (ncalls >= CSTACKMARK) {
+        /* not in error-handling zone; raise the error now */
+        L->nCcalls = (CSTACKMARK - 1);  /* enter error-handling zone */
+        luaG_runerror(L, "C stack overflow1");
+      }
+      /* else stack is in the error-handling zone;
+         allow message handler to work */
     }
   }
 }
@@ -153,13 +152,13 @@
   CallInfo *ci = L->ci;
   CallInfo *next = ci->next;
   ci->next = NULL;
-  L->nCcalls -= L->nci;  /* subtract removed elements from 'nCcalls' */
+  L->nCcalls += L->nci;  /* add removed elements back to 'nCcalls' */
   while ((ci = next) != NULL) {
     next = ci->next;
     luaM_free(L, ci);
     L->nci--;
   }
-  L->nCcalls += L->nci;  /* adjust result */
+  L->nCcalls -= L->nci;  /* adjust result */
 }
 
 
@@ -169,7 +168,7 @@
 void luaE_shrinkCI (lua_State *L) {
   CallInfo *ci = L->ci;
   CallInfo *next2;  /* next's next */
-  L->nCcalls -= L->nci;  /* subtract removed elements from 'nCcalls' */
+  L->nCcalls += L->nci;  /* add removed elements back to 'nCcalls' */
   /* while there are two nexts */
   while (ci->next != NULL && (next2 = ci->next->next) != NULL) {
     luaM_free(L, ci->next);  /* free next */
@@ -178,7 +177,7 @@
     next2->previous = ci;
     ci = next2;  /* keep next's next */
   }
-  L->nCcalls += L->nci;  /* adjust result */
+  L->nCcalls -= L->nci;  /* adjust result */
 }
 
 
@@ -264,7 +263,7 @@
   L->stacksize = 0;
   L->twups = L;  /* thread has no upvalues */
   L->errorJmp = NULL;
-  L->nCcalls = 0;
+  L->nCcalls = LUAI_MAXCSTACK + CSTACKERR;
   L->hook = NULL;
   L->hookmask = 0;
   L->basehookcount = 0;
diff --git a/lstate.h b/lstate.h
index 3bd5297..858da5b 100644
--- a/lstate.h
+++ b/lstate.h
@@ -64,28 +64,45 @@
 
 /*
 ** About 'nCcalls': each thread in Lua (a lua_State) keeps a count of
-** how many "C calls" it can do in the C stack, to avoid C-stack overflow.
-** This count is very rough approximation; it considers only recursive
-** functions inside the interpreter, as non-recursive calls can be
-** considered using a fixed (although unknown) amount of stack space.
+** how many "C calls" it still can do in the C stack, to avoid C-stack
+** overflow.  This count is very rough approximation; it considers only
+** recursive functions inside the interpreter, as non-recursive calls
+** can be considered using a fixed (although unknown) amount of stack
+** space.
 **
-** The count itself has two parts: the lower part is the count itself;
-** the higher part counts the number of non-yieldable calls in the stack.
+** The count has two parts: the lower part is the count itself; the
+** higher part counts the number of non-yieldable calls in the stack.
+** (They are together so that we can change both with one instruction.)
 **
 ** Because calls to external C functions can use of unkown amount
 ** of space (e.g., functions using an auxiliary buffer), calls
-** to these functions add more than one to the count.
+** to these functions add more than one to the count (see CSTACKCF).
 **
-** The proper count also includes the number of CallInfo structures
-** allocated by Lua, as a kind of "potential" calls. So, when Lua
-** calls a function (and "consumes" one CallInfo), it needs neither to
-** increment nor to check 'nCcalls', as its use of C stack is already
-** accounted for.
+** The proper count excludes the number of CallInfo structures allocated
+** by Lua, as a kind of "potential" calls. So, when Lua calls a function
+** (and "consumes" one CallInfo), it needs neither to decrement nor to
+** check 'nCcalls', as its use of C stack is already accounted for.
 */
 
 /* number of "C stack slots" used by an external C function */
 #define CSTACKCF	10
 
+
+/*
+** The C-stack size is sliced in the following zones:
+** - larger than CSTACKERR: normal stack;
+** - [CSTACKMARK, CSTACKERR]: buffer zone to signal a stack overflow;
+** - [CSTACKCF, CSTACKERRMARK]: error-handling zone;
+** - below CSTACKERRMARK: buffer zone to signal overflow during overflow;
+** (Because the counter can be decremented CSTACKCF at once, we need
+** the so called "buffer zones", with at least that size, to properly
+** detect a change from one zone to the next.)
+*/
+#define CSTACKERR	(8 * CSTACKCF)
+#define CSTACKMARK	(CSTACKERR - (CSTACKCF + 2))
+#define CSTACKERRMARK	(CSTACKCF + 2)
+
+
 /* true if this thread does not have non-yieldable calls in the stack */
 #define yieldable(L)		(((L)->nCcalls & 0xffff0000) == 0)
 
@@ -99,11 +116,11 @@
 /* Decrement the number of non-yieldable calls */
 #define decnny(L)	((L)->nCcalls -= 0x10000)
 
-/* Increment the number of non-yieldable calls and nCcalls */
-#define incXCcalls(L)	((L)->nCcalls += 0x10000 + CSTACKCF)
+/* Increment the number of non-yieldable calls and decrement nCcalls */
+#define incXCcalls(L)	((L)->nCcalls += 0x10000 - CSTACKCF)
 
-/* Decrement the number of non-yieldable calls and nCcalls */
-#define decXCcalls(L)	((L)->nCcalls -= 0x10000 + CSTACKCF)
+/* Decrement the number of non-yieldable calls and increment nCcalls */
+#define decXCcalls(L)	((L)->nCcalls -= 0x10000 - CSTACKCF)
 
 
 
@@ -336,7 +353,7 @@
 LUAI_FUNC void luaE_warning (lua_State *L, const char *msg, int tocont);
 
 
-#define luaE_exitCcall(L)	((L)->nCcalls--)
+#define luaE_exitCcall(L)	((L)->nCcalls++)
 
 #endif
 
diff --git a/testes/all.lua b/testes/all.lua
index 2e6fe03..72121e8 100644
--- a/testes/all.lua
+++ b/testes/all.lua
@@ -95,6 +95,8 @@
   end
 end
 
+local Cstacklevel
+
 local showmem
 if not T then
   local max = 0
@@ -104,6 +106,7 @@
     print(format("    ---- total memory: %s, max memory: %s ----\n",
           F(m), F(max)))
   end
+  Cstacklevel = function () return 0 end   -- no info about stack level
 else
   showmem = function ()
     T.checkmemory()
@@ -117,9 +120,16 @@
                  T.totalmem"string", T.totalmem"table", T.totalmem"function",
                  T.totalmem"userdata", T.totalmem"thread"))
   end
+
+  Cstacklevel = function ()
+    local _, _, ncalls, nci = T.stacklevel()
+    return ncalls  + nci   -- number of free slots in the C stack
+  end
 end
 
 
+local Cstack = Cstacklevel()
+
 --
 -- redefine dofile to run files through dump/undump
 --
@@ -211,6 +221,10 @@
 -- to survive outside block
 _G.showmem = showmem
 
+
+assert(Cstack == Cstacklevel(),
+  "should be at the same C-stack level it was when started the tests")
+
 end   --)
 
 local _G, showmem, print, format, clock, time, difftime,