mirror of
				https://gitlab.com/Syping/luaengineapp.git
				synced 2025-10-31 18:40:21 +01:00 
			
		
		
		
	Lua 5.4.2 runtime
This commit is contained in:
		
							parent
							
								
									ddc4ab91c4
								
							
						
					
					
						commit
						406905b359
					
				
					 33 changed files with 424 additions and 435 deletions
				
			
		|  | @ -55,6 +55,6 @@ win32 { | |||
|     RC_ICONS = ../../res/lua.ico | ||||
|     QMAKE_TARGET_COMPANY = "Syping" | ||||
|     QMAKE_TARGET_DESCRIPTION = "LuaEngine Runtime" | ||||
|     QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2019-2020 Syping" | ||||
|     QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2019-2021 Syping" | ||||
|     QMAKE_TARGET_PRODUCT = "luaengine" | ||||
| } | ||||
|  |  | |||
|  | @ -52,6 +52,6 @@ win32 { | |||
|     RC_ICONS = ../../res/lua.ico | ||||
|     QMAKE_TARGET_COMPANY = "Syping" | ||||
|     QMAKE_TARGET_DESCRIPTION = "LuaEngine Compiler" | ||||
|     QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2019-2020 Syping" | ||||
|     QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2019-2021 Syping" | ||||
|     QMAKE_TARGET_PRODUCT = "luaenginec" | ||||
| } | ||||
|  |  | |||
|  | @ -57,6 +57,6 @@ win32 { | |||
|     RC_ICONS = ../../res/lua.ico | ||||
|     QMAKE_TARGET_COMPANY = "Syping" | ||||
|     QMAKE_TARGET_DESCRIPTION = "LuaEngine CLI Runtime" | ||||
|     QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2020 Syping" | ||||
|     QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2020-2021 Syping" | ||||
|     QMAKE_TARGET_PRODUCT = "luaenginecli" | ||||
| } | ||||
|  |  | |||
|  | @ -1383,13 +1383,16 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { | |||
| 
 | ||||
| 
 | ||||
| static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { | ||||
|   static const UpVal *const nullup = NULL; | ||||
|   LClosure *f; | ||||
|   TValue *fi = index2value(L, fidx); | ||||
|   api_check(L, ttisLclosure(fi), "Lua function expected"); | ||||
|   f = clLvalue(fi); | ||||
|   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 */ | ||||
|   if (1 <= n && n <= f->p->sizeupvalues) | ||||
|     return &f->upvals[n - 1];  /* get its upvalue pointer */ | ||||
|   else | ||||
|     return (UpVal**)&nullup; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1401,11 +1404,14 @@ LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { | |||
|     } | ||||
|     case LUA_VCCL: {  /* C closure */ | ||||
|       CClosure *f = clCvalue(fi); | ||||
|       api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index"); | ||||
|       return &f->upvalue[n - 1]; | ||||
|     } | ||||
|       if (1 <= n && n <= f->nupvalues) | ||||
|         return &f->upvalue[n - 1]; | ||||
|       /* else */ | ||||
|     }  /* FALLTHROUGH */ | ||||
|     case LUA_VLCF: | ||||
|       return NULL;  /* light C functions have no upvalues */ | ||||
|     default: { | ||||
|       api_check(L, 0, "closure expected"); | ||||
|       api_check(L, 0, "function expected"); | ||||
|       return NULL; | ||||
|     } | ||||
|   } | ||||
|  | @ -1417,6 +1423,7 @@ LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, | |||
|   LClosure *f1; | ||||
|   UpVal **up1 = getupvalref(L, fidx1, n1, &f1); | ||||
|   UpVal **up2 = getupvalref(L, fidx2, n2, NULL); | ||||
|   api_check(L, *up1 != NULL && *up2 != NULL, "invalid upvalue index"); | ||||
|   *up1 = *up2; | ||||
|   luaC_objbarrier(L, f1, *up1); | ||||
| } | ||||
|  |  | |||
|  | @ -283,10 +283,10 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { | |||
| 
 | ||||
| 
 | ||||
| LUALIB_API int luaL_execresult (lua_State *L, int stat) { | ||||
|   const char *what = "exit";  /* type of termination */ | ||||
|   if (stat != 0 && errno != 0)  /* error with an 'errno'? */ | ||||
|     return luaL_fileresult(L, 0, NULL); | ||||
|   else { | ||||
|     const char *what = "exit";  /* type of termination */ | ||||
|     l_inspectstat(stat, what);  /* interpret result */ | ||||
|     if (*what == 'e' && stat == 0)  /* successful termination? */ | ||||
|       lua_pushboolean(L, 1); | ||||
|  | @ -1006,43 +1006,67 @@ static int panic (lua_State *L) { | |||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** Emit a warning. '*warnstate' means: | ||||
| ** 0 - warning system is off; | ||||
| ** 1 - ready to start a new message; | ||||
| ** 2 - previous message is to be continued. | ||||
| ** Warning functions: | ||||
| ** warnfoff: warning system is off | ||||
| ** warnfon: ready to start a new message | ||||
| ** warnfcont: previous message is to be continued | ||||
| */ | ||||
| static void warnf (void *ud, const char *message, int tocont) { | ||||
|   int *warnstate = (int *)ud; | ||||
|   if (*warnstate != 2 && !tocont && *message == '@') {  /* control message? */ | ||||
|     if (strcmp(message, "@off") == 0) | ||||
|       *warnstate = 0; | ||||
|     else if (strcmp(message, "@on") == 0) | ||||
|       *warnstate = 1; | ||||
|     return; | ||||
| static void warnfoff (void *ud, const char *message, int tocont); | ||||
| static void warnfon (void *ud, const char *message, int tocont); | ||||
| static void warnfcont (void *ud, const char *message, int tocont); | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** Check whether message is a control message. If so, execute the | ||||
| ** control or ignore it if unknown. | ||||
| */ | ||||
| static int checkcontrol (lua_State *L, const char *message, int tocont) { | ||||
|   if (tocont || *(message++) != '@')  /* not a control message? */ | ||||
|     return 0; | ||||
|   else { | ||||
|     if (strcmp(message, "off") == 0) | ||||
|       lua_setwarnf(L, warnfoff, L);  /* turn warnings off */ | ||||
|     else if (strcmp(message, "on") == 0) | ||||
|       lua_setwarnf(L, warnfon, L);   /* turn warnings on */ | ||||
|     return 1;  /* it was a control message */ | ||||
|   } | ||||
|   else if (*warnstate == 0)  /* warnings off? */ | ||||
|     return; | ||||
|   if (*warnstate == 1)  /* previous message was the last? */ | ||||
|     lua_writestringerror("%s", "Lua warning: ");  /* start a new warning */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void warnfoff (void *ud, const char *message, int tocont) { | ||||
|   checkcontrol((lua_State *)ud, message, tocont); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** Writes the message and handle 'tocont', finishing the message | ||||
| ** if needed and setting the next warn function. | ||||
| */ | ||||
| static void warnfcont (void *ud, const char *message, int tocont) { | ||||
|   lua_State *L = (lua_State *)ud; | ||||
|   lua_writestringerror("%s", message);  /* write message */ | ||||
|   if (tocont)  /* not the last part? */ | ||||
|     *warnstate = 2;  /* to be continued */ | ||||
|     lua_setwarnf(L, warnfcont, L);  /* to be continued */ | ||||
|   else {  /* last part */ | ||||
|     lua_writestringerror("%s", "\n");  /* finish message with end-of-line */ | ||||
|     *warnstate = 1;  /* ready to start a new message */ | ||||
|     lua_setwarnf(L, warnfon, L);  /* next call is a new message */ | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void warnfon (void *ud, const char *message, int tocont) { | ||||
|   if (checkcontrol((lua_State *)ud, message, tocont))  /* control message? */ | ||||
|     return;  /* nothing else to be done */ | ||||
|   lua_writestringerror("%s", "Lua warning: ");  /* start a new warning */ | ||||
|   warnfcont(ud, message, tocont);  /* finish processing */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| LUALIB_API lua_State *luaL_newstate (void) { | ||||
|   lua_State *L = lua_newstate(l_alloc, NULL); | ||||
|   if (L) { | ||||
|     int *warnstate;  /* space for warning state */ | ||||
|     lua_atpanic(L, &panic); | ||||
|     warnstate = (int *)lua_newuserdatauv(L, sizeof(int), 0); | ||||
|     luaL_ref(L, LUA_REGISTRYINDEX);  /* make sure it won't be collected */ | ||||
|     *warnstate = 0;  /* default is warnings off */ | ||||
|     lua_setwarnf(L, warnf, warnstate); | ||||
|     lua_setwarnf(L, warnfoff, L);  /* default is warnings off */ | ||||
|   } | ||||
|   return L; | ||||
| } | ||||
|  |  | |||
|  | @ -753,7 +753,7 @@ void luaK_setoneret (FuncState *fs, expdesc *e) { | |||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** Ensure that expression 'e' is not a variable (nor a constant). | ||||
| ** Ensure that expression 'e' is not a variable (nor a <const>). | ||||
| ** (Expression still may have jump lists.) | ||||
| */ | ||||
| void luaK_dischargevars (FuncState *fs, expdesc *e) { | ||||
|  | @ -805,8 +805,8 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { | |||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** Ensures expression value is in register 'reg' (and therefore | ||||
| ** 'e' will become a non-relocatable expression). | ||||
| ** Ensure expression value is in register 'reg', making 'e' a | ||||
| ** non-relocatable expression. | ||||
| ** (Expression still may have jump lists.) | ||||
| */ | ||||
| static void discharge2reg (FuncState *fs, expdesc *e, int reg) { | ||||
|  | @ -860,7 +860,8 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { | |||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** Ensures expression value is in any register. | ||||
| ** Ensure expression value is in a register, making 'e' a | ||||
| ** non-relocatable expression. | ||||
| ** (Expression still may have jump lists.) | ||||
| */ | ||||
| static void discharge2anyreg (FuncState *fs, expdesc *e) { | ||||
|  | @ -946,8 +947,11 @@ int luaK_exp2anyreg (FuncState *fs, expdesc *e) { | |||
|       exp2reg(fs, e, e->u.info);  /* put final result in it */ | ||||
|       return e->u.info; | ||||
|     } | ||||
|     /* else expression has jumps and cannot change its register
 | ||||
|        to hold the jump values, because it is a local variable. | ||||
|        Go through to the default case. */ | ||||
|   } | ||||
|   luaK_exp2nextreg(fs, e);  /* otherwise, use next available register */ | ||||
|   luaK_exp2nextreg(fs, e);  /* default: use next available register */ | ||||
|   return e->u.info; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -281,25 +281,33 @@ static int db_setupvalue (lua_State *L) { | |||
| ** Check whether a given upvalue from a given closure exists and | ||||
| ** returns its index | ||||
| */ | ||||
| static int checkupval (lua_State *L, int argf, int argnup) { | ||||
| static void *checkupval (lua_State *L, int argf, int argnup, int *pnup) { | ||||
|   void *id; | ||||
|   int nup = (int)luaL_checkinteger(L, argnup);  /* upvalue index */ | ||||
|   luaL_checktype(L, argf, LUA_TFUNCTION);  /* closure */ | ||||
|   luaL_argcheck(L, (lua_getupvalue(L, argf, nup) != NULL), argnup, | ||||
|                    "invalid upvalue index"); | ||||
|   return nup; | ||||
|   id = lua_upvalueid(L, argf, nup); | ||||
|   if (pnup) { | ||||
|     luaL_argcheck(L, id != NULL, argnup, "invalid upvalue index"); | ||||
|     *pnup = nup; | ||||
|   } | ||||
|   return id; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int db_upvalueid (lua_State *L) { | ||||
|   int n = checkupval(L, 1, 2); | ||||
|   lua_pushlightuserdata(L, lua_upvalueid(L, 1, n)); | ||||
|   void *id = checkupval(L, 1, 2, NULL); | ||||
|   if (id != NULL) | ||||
|     lua_pushlightuserdata(L, id); | ||||
|   else | ||||
|     luaL_pushfail(L); | ||||
|   return 1; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int db_upvaluejoin (lua_State *L) { | ||||
|   int n1 = checkupval(L, 1, 2); | ||||
|   int n2 = checkupval(L, 3, 4); | ||||
|   int n1, n2; | ||||
|   checkupval(L, 1, 2, &n1); | ||||
|   checkupval(L, 3, 4, &n2); | ||||
|   luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected"); | ||||
|   luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected"); | ||||
|   lua_upvaluejoin(L, 1, n1, 3, n2); | ||||
|  | @ -440,10 +448,7 @@ static int db_traceback (lua_State *L) { | |||
| static int db_setcstacklimit (lua_State *L) { | ||||
|   int limit = (int)luaL_checkinteger(L, 1); | ||||
|   int res = lua_setcstacklimit(L, limit); | ||||
|   if (res == 0) | ||||
|     lua_pushboolean(L, 0); | ||||
|   else | ||||
|     lua_pushinteger(L, res); | ||||
|   lua_pushinteger(L, res); | ||||
|   return 1; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -139,8 +139,7 @@ l_noret luaD_throw (lua_State *L, int errcode) { | |||
| 
 | ||||
| 
 | ||||
| int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { | ||||
|   global_State *g = G(L); | ||||
|   l_uint32 oldnCcalls = g->Cstacklimit - (L->nCcalls + L->nci); | ||||
|   l_uint32 oldnCcalls = L->nCcalls; | ||||
|   struct lua_longjmp lj; | ||||
|   lj.status = LUA_OK; | ||||
|   lj.previous = L->errorJmp;  /* chain new error handler */ | ||||
|  | @ -149,7 +148,7 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { | |||
|     (*f)(L, ud); | ||||
|   ); | ||||
|   L->errorJmp = lj.previous;  /* restore old error handler */ | ||||
|   L->nCcalls = g->Cstacklimit - oldnCcalls - L->nci; | ||||
|   L->nCcalls = oldnCcalls; | ||||
|   return lj.status; | ||||
| } | ||||
| 
 | ||||
|  | @ -183,21 +182,20 @@ static void correctstack (lua_State *L, StkId oldstack, StkId newstack) { | |||
| 
 | ||||
| 
 | ||||
| int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) { | ||||
|   int lim = L->stacksize; | ||||
|   StkId newstack = luaM_reallocvector(L, L->stack, lim, newsize, StackValue); | ||||
|   int lim = stacksize(L); | ||||
|   StkId newstack = luaM_reallocvector(L, L->stack, | ||||
|                       lim + EXTRA_STACK, newsize + EXTRA_STACK, StackValue); | ||||
|   lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); | ||||
|   lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); | ||||
|   if (unlikely(newstack == NULL)) {  /* reallocation failed? */ | ||||
|     if (raiseerror) | ||||
|       luaM_error(L); | ||||
|     else return 0;  /* do not raise an error */ | ||||
|   } | ||||
|   for (; lim < newsize; lim++) | ||||
|     setnilvalue(s2v(newstack + lim)); /* erase new segment */ | ||||
|     setnilvalue(s2v(newstack + lim + EXTRA_STACK)); /* erase new segment */ | ||||
|   correctstack(L, L->stack, newstack); | ||||
|   L->stack = newstack; | ||||
|   L->stacksize = newsize; | ||||
|   L->stack_last = L->stack + newsize - EXTRA_STACK; | ||||
|   L->stack_last = L->stack + newsize; | ||||
|   return 1; | ||||
| } | ||||
| 
 | ||||
|  | @ -207,51 +205,73 @@ int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) { | |||
| ** is true, raises any error; otherwise, return 0 in case of errors. | ||||
| */ | ||||
| int luaD_growstack (lua_State *L, int n, int raiseerror) { | ||||
|   int size = L->stacksize; | ||||
|   int newsize = 2 * size;  /* tentative new size */ | ||||
|   if (unlikely(size > LUAI_MAXSTACK)) {  /* need more space after extra size? */ | ||||
|   int size = stacksize(L); | ||||
|   if (unlikely(size > LUAI_MAXSTACK)) { | ||||
|     /* if stack is larger than maximum, thread is already using the
 | ||||
|        extra space reserved for errors, that is, thread is handling | ||||
|        a stack error; cannot grow further than that. */ | ||||
|     lua_assert(stacksize(L) == ERRORSTACKSIZE); | ||||
|     if (raiseerror) | ||||
|       luaD_throw(L, LUA_ERRERR);  /* error inside message handler */ | ||||
|     else return 0; | ||||
|     return 0;  /* if not 'raiseerror', just signal it */ | ||||
|   } | ||||
|   else { | ||||
|     int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; | ||||
|     int newsize = 2 * size;  /* tentative new size */ | ||||
|     int needed = cast_int(L->top - L->stack) + n; | ||||
|     if (newsize > LUAI_MAXSTACK)  /* cannot cross the limit */ | ||||
|       newsize = LUAI_MAXSTACK; | ||||
|     if (newsize < needed)  /* but must respect what was asked for */ | ||||
|       newsize = needed; | ||||
|     if (unlikely(newsize > LUAI_MAXSTACK)) {  /* stack overflow? */ | ||||
|     if (likely(newsize <= LUAI_MAXSTACK)) | ||||
|       return luaD_reallocstack(L, newsize, raiseerror); | ||||
|     else {  /* stack overflow */ | ||||
|       /* add extra size to be able to handle the error message */ | ||||
|       luaD_reallocstack(L, ERRORSTACKSIZE, raiseerror); | ||||
|       if (raiseerror) | ||||
|         luaG_runerror(L, "stack overflow"); | ||||
|       else return 0; | ||||
|       return 0; | ||||
|     } | ||||
|   }  /* else no errors */ | ||||
|   return luaD_reallocstack(L, newsize, raiseerror); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int stackinuse (lua_State *L) { | ||||
|   CallInfo *ci; | ||||
|   int res; | ||||
|   StkId lim = L->top; | ||||
|   for (ci = L->ci; ci != NULL; ci = ci->previous) { | ||||
|     if (lim < ci->top) lim = ci->top; | ||||
|   } | ||||
|   lua_assert(lim <= L->stack_last); | ||||
|   return cast_int(lim - L->stack) + 1;  /* part of stack in use */ | ||||
|   res = cast_int(lim - L->stack) + 1;  /* part of stack in use */ | ||||
|   if (res < LUA_MINSTACK) | ||||
|     res = LUA_MINSTACK;  /* ensure a minimum size */ | ||||
|   return res; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** If stack size is more than 3 times the current use, reduce that size | ||||
| ** to twice the current use. (So, the final stack size is at most 2/3 the | ||||
| ** previous size, and half of its entries are empty.) | ||||
| ** As a particular case, if stack was handling a stack overflow and now | ||||
| ** it is not, 'max' (limited by LUAI_MAXSTACK) will be smaller than | ||||
| ** stacksize (equal to ERRORSTACKSIZE in this case), and so the stack | ||||
| ** will be reduced to a "regular" size. | ||||
| */ | ||||
| void luaD_shrinkstack (lua_State *L) { | ||||
|   int inuse = stackinuse(L); | ||||
|   int goodsize = inuse + BASIC_STACK_SIZE; | ||||
|   if (goodsize > LUAI_MAXSTACK) | ||||
|     goodsize = LUAI_MAXSTACK;  /* respect stack limit */ | ||||
|   int nsize = inuse * 2;  /* proposed new size */ | ||||
|   int max = inuse * 3;  /* maximum "reasonable" size */ | ||||
|   if (max > LUAI_MAXSTACK) { | ||||
|     max = LUAI_MAXSTACK;  /* respect stack limit */ | ||||
|     if (nsize > LUAI_MAXSTACK) | ||||
|       nsize = LUAI_MAXSTACK; | ||||
|   } | ||||
|   /* if thread is currently not handling a stack overflow and its
 | ||||
|      good size is smaller than current size, shrink its stack */ | ||||
|   if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && goodsize < L->stacksize) | ||||
|     luaD_reallocstack(L, goodsize, 0);  /* ok if that fails */ | ||||
|      size is larger than maximum "reasonable" size, shrink it */ | ||||
|   if (inuse <= LUAI_MAXSTACK && stacksize(L) > max) | ||||
|     luaD_reallocstack(L, nsize, 0);  /* ok if that fails */ | ||||
|   else  /* don't change stack */ | ||||
|     condmovestack(L,{},{});  /* (change only for debugging) */ | ||||
|   luaE_shrinkCI(L);  /* shrink CI list */ | ||||
|  | @ -348,7 +368,7 @@ static StkId rethook (lua_State *L, CallInfo *ci, StkId firstres, int nres) { | |||
| 
 | ||||
| /*
 | ||||
| ** Check whether 'func' has a '__call' metafield. If so, put it in the | ||||
| ** stack, below original 'func', so that 'luaD_call' can call it. Raise | ||||
| ** stack, below original 'func', so that 'luaD_precall' can call it. Raise | ||||
| ** an error if there is no '__call' metafield. | ||||
| */ | ||||
| void luaD_tryfuncTM (lua_State *L, StkId func) { | ||||
|  | @ -449,12 +469,14 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) { | |||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** Call a function (C or Lua). The function to be called is at *func. | ||||
| ** The arguments are on the stack, right after the function. | ||||
| ** When returns, all the results are on the stack, starting at the original | ||||
| ** function position. | ||||
| ** Prepares the call to a function (C or Lua). For C functions, also do | ||||
| ** the call. The function to be called is at '*func'.  The arguments | ||||
| ** are on the stack, right after the function.  Returns the CallInfo | ||||
| ** to be executed, if it was a Lua function. Otherwise (a C function) | ||||
| ** returns NULL, with all the results on the stack, starting at the | ||||
| ** original function position. | ||||
| */ | ||||
| void luaD_call (lua_State *L, StkId func, int nresults) { | ||||
| CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { | ||||
|   lua_CFunction f; | ||||
|  retry: | ||||
|   switch (ttypetag(s2v(func))) { | ||||
|  | @ -482,7 +504,7 @@ void luaD_call (lua_State *L, StkId func, int nresults) { | |||
|       lua_lock(L); | ||||
|       api_checknelems(L, n); | ||||
|       luaD_poscall(L, ci, n); | ||||
|       break; | ||||
|       return NULL; | ||||
|     } | ||||
|     case LUA_VLCL: {  /* Lua function */ | ||||
|       CallInfo *ci; | ||||
|  | @ -494,15 +516,13 @@ void luaD_call (lua_State *L, StkId func, int nresults) { | |||
|       L->ci = ci = next_ci(L); | ||||
|       ci->nresults = nresults; | ||||
|       ci->u.l.savedpc = p->code;  /* starting point */ | ||||
|       ci->callstatus = 0; | ||||
|       ci->top = func + 1 + fsize; | ||||
|       ci->func = func; | ||||
|       L->ci = ci; | ||||
|       for (; narg < nfixparams; narg++) | ||||
|         setnilvalue(s2v(L->top++));  /* complete missing arguments */ | ||||
|       lua_assert(ci->top <= L->stack_last); | ||||
|       luaV_execute(L, ci);  /* run the function */ | ||||
|       break; | ||||
|       return ci; | ||||
|     } | ||||
|     default: {  /* not a function */ | ||||
|       checkstackGCp(L, 1, func);  /* space for metamethod */ | ||||
|  | @ -513,17 +533,37 @@ void luaD_call (lua_State *L, StkId func, int nresults) { | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** Call a function (C or Lua) through C. 'inc' can be 1 (increment | ||||
| ** number of recursive invocations in the C stack) or nyci (the same | ||||
| ** plus increment number of non-yieldable calls). | ||||
| */ | ||||
| static void ccall (lua_State *L, StkId func, int nResults, int inc) { | ||||
|   CallInfo *ci; | ||||
|   L->nCcalls += inc; | ||||
|   if (unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) | ||||
|     luaE_checkcstack(L); | ||||
|   if ((ci = luaD_precall(L, func, nResults)) != NULL) {  /* Lua function? */ | ||||
|     ci->callstatus = CIST_FRESH;  /* mark that it is a "fresh" execute */ | ||||
|     luaV_execute(L, ci);  /* call it */ | ||||
|   } | ||||
|   L->nCcalls -= inc; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** External interface for 'ccall' | ||||
| */ | ||||
| void luaD_call (lua_State *L, StkId func, int nResults) { | ||||
|   ccall(L, func, nResults, 1); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** Similar to 'luaD_call', but does not allow yields during the call. | ||||
| */ | ||||
| void luaD_callnoyield (lua_State *L, StkId func, int nResults) { | ||||
|   incXCcalls(L); | ||||
|   if (getCcalls(L) <= CSTACKERR) {  /* possible C stack overflow? */ | ||||
|     luaE_exitCcall(L);  /* to compensate decrement in next call */ | ||||
|     luaE_enterCcall(L);  /* check properly */ | ||||
|   } | ||||
|   luaD_call(L, func, nResults); | ||||
|   decXCcalls(L); | ||||
|   ccall(L, func, nResults, nyci); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -601,12 +641,12 @@ static int recover (lua_State *L, int status) { | |||
|   if (ci == NULL) return 0;  /* no recovery point */ | ||||
|   /* "finish" luaD_pcall */ | ||||
|   oldtop = restorestack(L, ci->u2.funcidx); | ||||
|   luaF_close(L, oldtop, status);  /* may change the stack */ | ||||
|   oldtop = restorestack(L, ci->u2.funcidx); | ||||
|   luaD_seterrorobj(L, status, oldtop); | ||||
|   L->ci = ci; | ||||
|   L->allowhook = getoah(ci->callstatus);  /* restore original 'allowhook' */ | ||||
|   luaD_shrinkstack(L); | ||||
|   status = luaF_close(L, oldtop, status);  /* may change the stack */ | ||||
|   oldtop = restorestack(L, ci->u2.funcidx); | ||||
|   luaD_seterrorobj(L, status, oldtop); | ||||
|   luaD_shrinkstack(L);   /* restore stack size in case of overflow */ | ||||
|   L->errfunc = ci->u.c.old_errfunc; | ||||
|   return 1;  /* continue running the coroutine */ | ||||
| } | ||||
|  | @ -637,12 +677,12 @@ static void resume (lua_State *L, void *ud) { | |||
|   int n = *(cast(int*, ud));  /* number of arguments */ | ||||
|   StkId firstArg = L->top - n;  /* first argument */ | ||||
|   CallInfo *ci = L->ci; | ||||
|   if (L->status == LUA_OK) {  /* starting a coroutine? */ | ||||
|     luaD_call(L, firstArg - 1, LUA_MULTRET); | ||||
|   } | ||||
|   if (L->status == LUA_OK)  /* starting a coroutine? */ | ||||
|     ccall(L, firstArg - 1, LUA_MULTRET, 1);  /* just call its body */ | ||||
|   else {  /* resuming from previous yield */ | ||||
|     lua_assert(L->status == LUA_YIELD); | ||||
|     L->status = LUA_OK;  /* mark that it is running (again) */ | ||||
|     luaE_incCstack(L);  /* control the C stack */ | ||||
|     if (isLua(ci))  /* yielded inside a hook? */ | ||||
|       luaV_execute(L, ci);  /* just continue running Lua code */ | ||||
|     else {  /* 'common' yield */ | ||||
|  | @ -670,12 +710,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, | |||
|   } | ||||
|   else if (L->status != LUA_YIELD)  /* ended with errors? */ | ||||
|     return resume_error(L, "cannot resume dead coroutine", nargs); | ||||
|   if (from == NULL) | ||||
|     L->nCcalls = CSTACKTHREAD; | ||||
|   else  /* correct 'nCcalls' for this thread */ | ||||
|     L->nCcalls = getCcalls(from) - L->nci - CSTACKCF; | ||||
|   if (L->nCcalls <= CSTACKERR) | ||||
|     return resume_error(L, "C stack overflow", nargs); | ||||
|   L->nCcalls = (from) ? getCcalls(from) : 0; | ||||
|   luai_userstateresume(L, nargs); | ||||
|   api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); | ||||
|   status = luaD_rawrunprotected(L, resume, &nargs); | ||||
|  | @ -754,7 +789,7 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u, | |||
|     status = luaF_close(L, oldtop, status); | ||||
|     oldtop = restorestack(L, old_top);  /* previous call may change stack */ | ||||
|     luaD_seterrorobj(L, status, oldtop); | ||||
|     luaD_shrinkstack(L); | ||||
|     luaD_shrinkstack(L);   /* restore stack size in case of overflow */ | ||||
|   } | ||||
|   L->errfunc = old_errfunc; | ||||
|   return status; | ||||
|  |  | |||
|  | @ -59,6 +59,7 @@ LUAI_FUNC void luaD_hook (lua_State *L, int event, int line, | |||
|                                         int fTransfer, int nTransfer); | ||||
| LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci); | ||||
| LUAI_FUNC void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n); | ||||
| LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults); | ||||
| 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 void luaD_tryfuncTM (lua_State *L, StkId func); | ||||
|  |  | |||
|  | @ -53,7 +53,7 @@ void luaF_initupvals (lua_State *L, LClosure *cl) { | |||
|     uv->v = &uv->u.value;  /* make it closed */ | ||||
|     setnilvalue(uv->v); | ||||
|     cl->upvals[i] = uv; | ||||
|     luaC_objbarrier(L, cl, o); | ||||
|     luaC_objbarrier(L, cl, uv); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -161,18 +161,17 @@ static void linkgclist_ (GCObject *o, GCObject **pnext, GCObject **list) { | |||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** Clear keys for empty entries in tables. If entry is empty | ||||
| ** and its key is not marked, mark its entry as dead. This allows the | ||||
| ** collection of the key, but keeps its entry in the table (its removal | ||||
| ** could break a chain). The main feature of a dead key is that it must | ||||
| ** be different from any other value, to do not disturb searches. | ||||
| ** Other places never manipulate dead keys, because its associated empty | ||||
| ** value is enough to signal that the entry is logically empty. | ||||
| ** Clear keys for empty entries in tables. If entry is empty, mark its | ||||
| ** entry as dead. This allows the collection of the key, but keeps its | ||||
| ** entry in the table: its removal could break a chain and could break | ||||
| ** a table traversal.  Other places never manipulate dead keys, because | ||||
| ** its associated empty value is enough to signal that the entry is | ||||
| ** logically empty. | ||||
| */ | ||||
| static void clearkey (Node *n) { | ||||
|   lua_assert(isempty(gval(n))); | ||||
|   if (keyiswhite(n)) | ||||
|     setdeadkey(n);  /* unused and unmarked key; remove it */ | ||||
|   if (keyiscollectable(n)) | ||||
|     setdeadkey(n);  /* unused key; remove it */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -301,7 +300,7 @@ static void reallymarkobject (global_State *g, GCObject *o) { | |||
|       if (upisopen(uv)) | ||||
|         set2gray(uv);  /* open upvalues are kept gray */ | ||||
|       else | ||||
|         set2black(o);  /* closed upvalues are visited here */ | ||||
|         set2black(uv);  /* closed upvalues are visited here */ | ||||
|       markvalue(g, uv->v);  /* mark its content */ | ||||
|       break; | ||||
|     } | ||||
|  | @ -309,7 +308,7 @@ static void reallymarkobject (global_State *g, GCObject *o) { | |||
|       Udata *u = gco2u(o); | ||||
|       if (u->nuvalue == 0) {  /* no user values? */ | ||||
|         markobjectN(g, u->metatable);  /* mark its metatable */ | ||||
|         set2black(o);  /* nothing else to mark */ | ||||
|         set2black(u);  /* nothing else to mark */ | ||||
|         break; | ||||
|       } | ||||
|       /* else... */ | ||||
|  | @ -633,9 +632,8 @@ static int traversethread (global_State *g, lua_State *th) { | |||
|   for (uv = th->openupval; uv != NULL; uv = uv->u.open.next) | ||||
|     markobject(g, uv);  /* open upvalues cannot be collected */ | ||||
|   if (g->gcstate == GCSatomic) {  /* final traversal? */ | ||||
|     StkId lim = th->stack + th->stacksize;  /* real end of stack */ | ||||
|     for (; o < lim; o++)  /* clear not-marked stack slice */ | ||||
|       setnilvalue(s2v(o)); | ||||
|     for (; o < th->stack_last + EXTRA_STACK; o++) | ||||
|       setnilvalue(s2v(o));  /* clear dead stack slice */ | ||||
|     /* 'remarkupvals' may have removed thread from 'twups' list */ | ||||
|     if (!isintwups(th) && th->openupval != NULL) { | ||||
|       th->twups = g->twups;  /* link it back to the list */ | ||||
|  | @ -644,7 +642,7 @@ static int traversethread (global_State *g, lua_State *th) { | |||
|   } | ||||
|   else if (!g->gcemergency) | ||||
|     luaD_shrinkstack(th); /* do not change stack in emergency cycle */ | ||||
|   return 1 + th->stacksize; | ||||
|   return 1 + stacksize(th); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -771,12 +769,16 @@ static void freeobj (lua_State *L, GCObject *o) { | |||
|     case LUA_VUPVAL: | ||||
|       freeupval(L, gco2upv(o)); | ||||
|       break; | ||||
|     case LUA_VLCL: | ||||
|       luaM_freemem(L, o, sizeLclosure(gco2lcl(o)->nupvalues)); | ||||
|     case LUA_VLCL: { | ||||
|       LClosure *cl = gco2lcl(o); | ||||
|       luaM_freemem(L, cl, sizeLclosure(cl->nupvalues)); | ||||
|       break; | ||||
|     case LUA_VCCL: | ||||
|       luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); | ||||
|     } | ||||
|     case LUA_VCCL: { | ||||
|       CClosure *cl = gco2ccl(o); | ||||
|       luaM_freemem(L, cl, sizeCclosure(cl->nupvalues)); | ||||
|       break; | ||||
|     } | ||||
|     case LUA_VTABLE: | ||||
|       luaH_free(L, gco2t(o)); | ||||
|       break; | ||||
|  | @ -788,13 +790,17 @@ static void freeobj (lua_State *L, GCObject *o) { | |||
|       luaM_freemem(L, o, sizeudata(u->nuvalue, u->len)); | ||||
|       break; | ||||
|     } | ||||
|     case LUA_VSHRSTR: | ||||
|       luaS_remove(L, gco2ts(o));  /* remove it from hash table */ | ||||
|       luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen)); | ||||
|     case LUA_VSHRSTR: { | ||||
|       TString *ts = gco2ts(o); | ||||
|       luaS_remove(L, ts);  /* remove it from hash table */ | ||||
|       luaM_freemem(L, ts, sizelstring(ts->shrlen)); | ||||
|       break; | ||||
|     case LUA_VLNGSTR: | ||||
|       luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen)); | ||||
|     } | ||||
|     case LUA_VLNGSTR: { | ||||
|       TString *ts = gco2ts(o); | ||||
|       luaM_freemem(L, ts, sizelstring(ts->u.lnglen)); | ||||
|       break; | ||||
|     } | ||||
|     default: lua_assert(0); | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -254,9 +254,10 @@ static int read_numeral (LexState *ls, SemInfo *seminfo) { | |||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** reads a sequence '[=*[' or ']=*]', leaving the last bracket. | ||||
| ** If sequence is well formed, return its number of '='s + 2; otherwise, | ||||
| ** return 1 if there is no '='s or 0 otherwise (an unfinished '[==...'). | ||||
| ** read a sequence '[=*[' or ']=*]', leaving the last bracket. If | ||||
| ** sequence is well formed, return its number of '='s + 2; otherwise, | ||||
| ** return 1 if it is a single bracket (no '='s and no 2nd bracket); | ||||
| ** otherwise (an unfinished '[==...') return 0. | ||||
| */ | ||||
| static size_t skip_sep (LexState *ls) { | ||||
|   size_t count = 0; | ||||
|  | @ -481,34 +482,34 @@ static int llex (LexState *ls, SemInfo *seminfo) { | |||
|       } | ||||
|       case '=': { | ||||
|         next(ls); | ||||
|         if (check_next1(ls, '=')) return TK_EQ; | ||||
|         if (check_next1(ls, '=')) return TK_EQ;  /* '==' */ | ||||
|         else return '='; | ||||
|       } | ||||
|       case '<': { | ||||
|         next(ls); | ||||
|         if (check_next1(ls, '=')) return TK_LE; | ||||
|         else if (check_next1(ls, '<')) return TK_SHL; | ||||
|         if (check_next1(ls, '=')) return TK_LE;  /* '<=' */ | ||||
|         else if (check_next1(ls, '<')) return TK_SHL;  /* '<<' */ | ||||
|         else return '<'; | ||||
|       } | ||||
|       case '>': { | ||||
|         next(ls); | ||||
|         if (check_next1(ls, '=')) return TK_GE; | ||||
|         else if (check_next1(ls, '>')) return TK_SHR; | ||||
|         if (check_next1(ls, '=')) return TK_GE;  /* '>=' */ | ||||
|         else if (check_next1(ls, '>')) return TK_SHR;  /* '>>' */ | ||||
|         else return '>'; | ||||
|       } | ||||
|       case '/': { | ||||
|         next(ls); | ||||
|         if (check_next1(ls, '/')) return TK_IDIV; | ||||
|         if (check_next1(ls, '/')) return TK_IDIV;  /* '//' */ | ||||
|         else return '/'; | ||||
|       } | ||||
|       case '~': { | ||||
|         next(ls); | ||||
|         if (check_next1(ls, '=')) return TK_NE; | ||||
|         if (check_next1(ls, '=')) return TK_NE;  /* '~=' */ | ||||
|         else return '~'; | ||||
|       } | ||||
|       case ':': { | ||||
|         next(ls); | ||||
|         if (check_next1(ls, ':')) return TK_DBCOLON; | ||||
|         if (check_next1(ls, ':')) return TK_DBCOLON;  /* '::' */ | ||||
|         else return ':'; | ||||
|       } | ||||
|       case '"': case '\'': {  /* short literal strings */ | ||||
|  | @ -547,7 +548,7 @@ static int llex (LexState *ls, SemInfo *seminfo) { | |||
|             return TK_NAME; | ||||
|           } | ||||
|         } | ||||
|         else {  /* single-char tokens (+ - / ...) */ | ||||
|         else {  /* single-char tokens ('+', '*', '%', '{', '}', ...) */ | ||||
|           int c = ls->current; | ||||
|           next(ls); | ||||
|           return c; | ||||
|  |  | |||
|  | @ -234,6 +234,17 @@ typedef l_uint32 Instruction; | |||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** Maximum depth for nested C calls, syntactical nested non-terminals, | ||||
| ** and other features implemented through recursion in C. (Value must | ||||
| ** fit in a 16-bit unsigned integer. It must also be compatible with | ||||
| ** the size of the C stack.) | ||||
| */ | ||||
| #if !defined(LUAI_MAXCCALLS) | ||||
| #define LUAI_MAXCCALLS		200 | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** macros that are executed whenever program enters the Lua core | ||||
| ** ('lua_lock') and leaves the core ('lua_unlock') | ||||
|  | @ -315,7 +326,8 @@ typedef l_uint32 Instruction; | |||
| 
 | ||||
| /* exponentiation */ | ||||
| #if !defined(luai_numpow) | ||||
| #define luai_numpow(L,a,b)      ((void)L, l_mathop(pow)(a,b)) | ||||
| #define luai_numpow(L,a,b)  \ | ||||
|   ((void)L, (b == 2) ? (a)*(a) : l_mathop(pow)(a,b)) | ||||
| #endif | ||||
| 
 | ||||
| /* the others are quite standard operations */ | ||||
|  | @ -344,7 +356,7 @@ typedef l_uint32 Instruction; | |||
| #else | ||||
| /* realloc stack keeping its size */ | ||||
| #define condmovestack(L,pre,pos)  \ | ||||
|   { int sz_ = (L)->stacksize; pre; luaD_reallocstack((L), sz_, 0); pos; } | ||||
|   { int sz_ = stacksize(L); pre; luaD_reallocstack((L), sz_, 0); pos; } | ||||
| #endif | ||||
| 
 | ||||
| #if !defined(HARDMEMTESTS) | ||||
|  |  | |||
|  | @ -258,7 +258,7 @@ static const char *l_str2d (const char *s, lua_Number *result) { | |||
|   if (endptr == NULL) {  /* failed? may be a different locale */ | ||||
|     char buff[L_MAXLENNUM + 1]; | ||||
|     const char *pdot = strchr(s, '.'); | ||||
|     if (strlen(s) > L_MAXLENNUM || pdot == NULL) | ||||
|     if (pdot == NULL || strlen(s) > L_MAXLENNUM) | ||||
|       return NULL;  /* string too long or no dot; fail */ | ||||
|     strcpy(buff, s);  /* copy string to buffer */ | ||||
|     buff[pdot - s] = lua_getlocaledecpoint();  /* correct decimal point */ | ||||
|  |  | |||
|  | @ -21,10 +21,12 @@ | |||
| */ | ||||
| #define LUA_TUPVAL	LUA_NUMTYPES  /* upvalues */ | ||||
| #define LUA_TPROTO	(LUA_NUMTYPES+1)  /* function prototypes */ | ||||
| #define LUA_TDEADKEY	(LUA_NUMTYPES+2)  /* removed keys in tables */ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** number of all possible types (including LUA_TNONE) | ||||
| ** number of all possible types (including LUA_TNONE but excluding DEADKEY) | ||||
| */ | ||||
| #define LUA_TOTALTYPES		(LUA_TPROTO + 2) | ||||
| 
 | ||||
|  | @ -555,7 +557,7 @@ typedef struct Proto { | |||
| 
 | ||||
| /*
 | ||||
| ** {================================================================== | ||||
| ** Closures | ||||
| ** Functions | ||||
| ** =================================================================== | ||||
| */ | ||||
| 
 | ||||
|  | @ -743,13 +745,13 @@ typedef struct Table { | |||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** Use a "nil table" to mark dead keys in a table. Those keys serve | ||||
| ** to keep space for removed entries, which may still be part of | ||||
| ** chains. Note that the 'keytt' does not have the BIT_ISCOLLECTABLE | ||||
| ** set, so these values are considered not collectable and are different | ||||
| ** from any valid value. | ||||
| ** Dead keys in tables have the tag DEADKEY but keep their original | ||||
| ** gcvalue. This distinguishes them from regular keys but allows them to | ||||
| ** be found when searched in a special way. ('next' needs that to find | ||||
| ** keys removed from a table during a traversal.) | ||||
| */ | ||||
| #define setdeadkey(n)	(keytt(n) = LUA_TTABLE, gckey(n) = NULL) | ||||
| #define setdeadkey(node)	(keytt(node) = LUA_TDEADKEY) | ||||
| #define keyisdead(node)		(keytt(node) == LUA_TDEADKEY) | ||||
| 
 | ||||
| /* }================================================================== */ | ||||
| 
 | ||||
|  |  | |||
|  | @ -261,7 +261,7 @@ OP_MMBINK,/*	A B C k		call C metamethod over R[A] and K[B]	*/ | |||
| OP_UNM,/*	A B	R[A] := -R[B]					*/ | ||||
| OP_BNOT,/*	A B	R[A] := ~R[B]					*/ | ||||
| OP_NOT,/*	A B	R[A] := not R[B]				*/ | ||||
| OP_LEN,/*	A B	R[A] := length of R[B]				*/ | ||||
| OP_LEN,/*	A B	R[A] := #R[B] (length operator)			*/ | ||||
| 
 | ||||
| OP_CONCAT,/*	A B	R[A] := R[A].. ... ..R[A + B - 1]		*/ | ||||
| 
 | ||||
|  | @ -297,7 +297,7 @@ OP_TFORPREP,/*	A Bx	create upvalue for R[A + 3]; pc+=Bx		*/ | |||
| OP_TFORCALL,/*	A C	R[A+4], ... ,R[A+3+C] := R[A](R[A+1], R[A+2]);	*/ | ||||
| OP_TFORLOOP,/*	A Bx	if R[A+2] ~= nil then { R[A]=R[A+2]; pc -= Bx }	*/ | ||||
| 
 | ||||
| OP_SETLIST,/*	A B C k	R[A][(C-1)*FPF+i] := R[A+i], 1 <= i <= B	*/ | ||||
| OP_SETLIST,/*	A B C k	R[A][C+i] := R[A+i], 1 <= i <= B		*/ | ||||
| 
 | ||||
| OP_CLOSURE,/*	A Bx	R[A] := closure(KPROTO[Bx])			*/ | ||||
| 
 | ||||
|  |  | |||
|  | @ -489,12 +489,10 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** Macros to limit the maximum recursion depth while parsing | ||||
| */ | ||||
| #define enterlevel(ls)	luaE_enterCcall((ls)->L) | ||||
| #define enterlevel(ls)	luaE_incCstack(ls->L) | ||||
| 
 | ||||
| #define leavelevel(ls)	luaE_exitCcall((ls)->L) | ||||
| 
 | ||||
| #define leavelevel(ls) ((ls)->L->nCcalls--) | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  | @ -947,7 +945,7 @@ static void setvararg (FuncState *fs, int nparams) { | |||
| 
 | ||||
| 
 | ||||
| static void parlist (LexState *ls) { | ||||
|   /* parlist -> [ param { ',' param } ] */ | ||||
|   /* parlist -> [ {NAME ','} (NAME | '...') ] */ | ||||
|   FuncState *fs = ls->fs; | ||||
|   Proto *f = fs->f; | ||||
|   int nparams = 0; | ||||
|  | @ -955,12 +953,12 @@ static void parlist (LexState *ls) { | |||
|   if (ls->t.token != ')') {  /* is 'parlist' not empty? */ | ||||
|     do { | ||||
|       switch (ls->t.token) { | ||||
|         case TK_NAME: {  /* param -> NAME */ | ||||
|         case TK_NAME: { | ||||
|           new_localvar(ls, str_checkname(ls)); | ||||
|           nparams++; | ||||
|           break; | ||||
|         } | ||||
|         case TK_DOTS: {  /* param -> '...' */ | ||||
|         case TK_DOTS: { | ||||
|           luaX_next(ls); | ||||
|           isvararg = 1; | ||||
|           break; | ||||
|  | @ -1625,59 +1623,21 @@ static void forstat (LexState *ls, int line) { | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** Check whether next instruction is a single jump (a 'break', a 'goto' | ||||
| ** to a forward label, or a 'goto' to a backward label with no variable | ||||
| ** to close). If so, set the name of the 'label' it is jumping to | ||||
| ** ("break" for a 'break') or to where it is jumping to ('target') and | ||||
| ** return true. If not a single jump, leave input unchanged, to be | ||||
| ** handled as a regular statement. | ||||
| */ | ||||
| static int issinglejump (LexState *ls, TString **label, int *target) { | ||||
|   if (testnext(ls, TK_BREAK)) {  /* a break? */ | ||||
|     *label = luaS_newliteral(ls->L, "break"); | ||||
|     return 1; | ||||
|   } | ||||
|   else if (ls->t.token != TK_GOTO || luaX_lookahead(ls) != TK_NAME) | ||||
|     return 0;  /* not a valid goto */ | ||||
|   else { | ||||
|     TString *lname = ls->lookahead.seminfo.ts;  /* label's id */ | ||||
|     Labeldesc *lb = findlabel(ls, lname); | ||||
|     if (lb) {  /* a backward jump? */ | ||||
|       /* does it need to close variables? */ | ||||
|       if (luaY_nvarstack(ls->fs) > stacklevel(ls->fs, lb->nactvar)) | ||||
|         return 0;  /* not a single jump; cannot optimize */ | ||||
|       *target = lb->pc; | ||||
|     } | ||||
|     else  /* jump forward */ | ||||
|       *label = lname; | ||||
|     luaX_next(ls);  /* skip goto */ | ||||
|     luaX_next(ls);  /* skip name */ | ||||
|     return 1; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void test_then_block (LexState *ls, int *escapelist) { | ||||
|   /* test_then_block -> [IF | ELSEIF] cond THEN block */ | ||||
|   BlockCnt bl; | ||||
|   int line; | ||||
|   FuncState *fs = ls->fs; | ||||
|   TString *jlb = NULL; | ||||
|   int target = NO_JUMP; | ||||
|   expdesc v; | ||||
|   int jf;  /* instruction to skip 'then' code (if condition is false) */ | ||||
|   luaX_next(ls);  /* skip IF or ELSEIF */ | ||||
|   expr(ls, &v);  /* read condition */ | ||||
|   checknext(ls, TK_THEN); | ||||
|   line = ls->linenumber; | ||||
|   if (issinglejump(ls, &jlb, &target)) {  /* 'if x then goto' ? */ | ||||
|     luaK_goiffalse(ls->fs, &v);  /* will jump to label if condition is true */ | ||||
|   if (ls->t.token == TK_BREAK) {  /* 'if x then break' ? */ | ||||
|     int line = ls->linenumber; | ||||
|     luaK_goiffalse(ls->fs, &v);  /* will jump if condition is true */ | ||||
|     luaX_next(ls);  /* skip 'break' */ | ||||
|     enterblock(fs, &bl, 0);  /* must enter block before 'goto' */ | ||||
|     if (jlb != NULL)  /* forward jump? */ | ||||
|       newgotoentry(ls, jlb, line, v.t);  /* will be resolved later */ | ||||
|     else  /* backward jump */ | ||||
|       luaK_patchlist(fs, v.t, target);  /* jump directly to 'target' */ | ||||
|     newgotoentry(ls, luaS_newliteral(ls->L, "break"), line, v.t); | ||||
|     while (testnext(ls, ';')) {}  /* skip semicolons */ | ||||
|     if (block_follow(ls, 0)) {  /* jump is the entire block? */ | ||||
|       leaveblock(fs); | ||||
|  | @ -1686,7 +1646,7 @@ static void test_then_block (LexState *ls, int *escapelist) { | |||
|     else  /* must skip over 'then' part if condition is false */ | ||||
|       jf = luaK_jump(fs); | ||||
|   } | ||||
|   else {  /* regular case (not a jump) */ | ||||
|   else {  /* regular case (not a break) */ | ||||
|     luaK_goiftrue(ls->fs, &v);  /* skip over block if condition is false */ | ||||
|     enterblock(fs, &bl, 0); | ||||
|     jf = v.f; | ||||
|  | @ -1754,7 +1714,7 @@ static void checktoclose (LexState *ls, int level) { | |||
| 
 | ||||
| 
 | ||||
| static void localstat (LexState *ls) { | ||||
|   /* stat -> LOCAL ATTRIB NAME {',' ATTRIB NAME} ['=' explist] */ | ||||
|   /* stat -> LOCAL NAME ATTRIB { ',' NAME ATTRIB } ['=' explist] */ | ||||
|   FuncState *fs = ls->fs; | ||||
|   int toclose = -1;  /* index of to-be-closed variable (if any) */ | ||||
|   Vardesc *var;  /* last variable */ | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ | |||
| 
 | ||||
| /* kinds of variables/expressions */ | ||||
| typedef enum { | ||||
|   VVOID,  /* when 'expdesc' describes the last expression a list,
 | ||||
|   VVOID,  /* when 'expdesc' describes the last expression of a list,
 | ||||
|              this kind means an empty list (so, no expression) */ | ||||
|   VNIL,  /* constant nil */ | ||||
|   VTRUE,  /* constant true */ | ||||
|  | @ -38,7 +38,8 @@ typedef enum { | |||
|   VLOCAL,  /* local variable; var.sidx = stack index (local register);
 | ||||
|               var.vidx = relative index in 'actvar.arr'  */ | ||||
|   VUPVAL,  /* upvalue variable; info = index of upvalue in 'upvalues' */ | ||||
|   VCONST,  /* compile-time constant; info = absolute index in 'actvar.arr'  */ | ||||
|   VCONST,  /* compile-time <const> variable;
 | ||||
|               info = absolute index in 'actvar.arr'  */ | ||||
|   VINDEXED,  /* indexed variable;
 | ||||
|                 ind.t = table register; | ||||
|                 ind.idx = key's R index */ | ||||
|  |  | |||
|  | @ -76,7 +76,7 @@ static unsigned int luai_makeseed (lua_State *L) { | |||
|   addbuff(buff, p, &h);  /* local variable */ | ||||
|   addbuff(buff, p, &lua_newstate);  /* public function */ | ||||
|   lua_assert(p == sizeof(buff)); | ||||
|   return luaS_hash(buff, p, h, 1); | ||||
|   return luaS_hash(buff, p, h); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
|  | @ -97,66 +97,14 @@ void luaE_setdebt (global_State *g, l_mem debt) { | |||
| 
 | ||||
| 
 | ||||
| LUA_API int lua_setcstacklimit (lua_State *L, unsigned int limit) { | ||||
|   global_State *g = G(L); | ||||
|   int ccalls; | ||||
|   luaE_freeCI(L);  /* release unused CIs */ | ||||
|   ccalls = getCcalls(L); | ||||
|   if (limit >= 40000) | ||||
|     return 0;  /* out of bounds */ | ||||
|   limit += CSTACKERR; | ||||
|   if (L != g-> mainthread) | ||||
|     return 0;  /* only main thread can change the C stack */ | ||||
|   else if (ccalls <= CSTACKERR) | ||||
|     return 0;  /* handling overflow */ | ||||
|   else { | ||||
|     int diff = limit - g->Cstacklimit; | ||||
|     if (ccalls + diff <= CSTACKERR) | ||||
|       return 0;  /* new limit would cause an overflow */ | ||||
|     g->Cstacklimit = limit;  /* set new limit */ | ||||
|     L->nCcalls += diff;  /* correct 'nCcalls' */ | ||||
|     return limit - diff - CSTACKERR;  /* success; return previous limit */ | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** 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 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 <= CSTACKERR) {  /* possible overflow? */ | ||||
|     luaE_freeCI(L);  /* release unused CIs */ | ||||
|     ncalls = getCcalls(L);  /* update call count */ | ||||
|     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 overflow"); | ||||
|       } | ||||
|       /* else stack is in the error-handling zone;
 | ||||
|          allow message handler to work */ | ||||
|     } | ||||
|   } | ||||
|   UNUSED(L); UNUSED(limit); | ||||
|   return LUAI_MAXCCALLS;  /* warning?? */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| CallInfo *luaE_extendCI (lua_State *L) { | ||||
|   CallInfo *ci; | ||||
|   lua_assert(L->ci->next == NULL); | ||||
|   luaE_enterCcall(L); | ||||
|   ci = luaM_new(L, CallInfo); | ||||
|   lua_assert(L->ci->next == NULL); | ||||
|   L->ci->next = ci; | ||||
|  | @ -175,13 +123,11 @@ void luaE_freeCI (lua_State *L) { | |||
|   CallInfo *ci = L->ci; | ||||
|   CallInfo *next = ci->next; | ||||
|   ci->next = NULL; | ||||
|   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 */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -194,7 +140,6 @@ void luaE_shrinkCI (lua_State *L) { | |||
|   CallInfo *next; | ||||
|   if (ci == NULL) | ||||
|     return;  /* no extra elements */ | ||||
|   L->nCcalls += L->nci;  /* add removed elements back to 'nCcalls' */ | ||||
|   while ((next = ci->next) != NULL) {  /* two extra elements? */ | ||||
|     CallInfo *next2 = next->next;  /* next's next */ | ||||
|     ci->next = next2;  /* remove next from the list */ | ||||
|  | @ -207,19 +152,39 @@ void luaE_shrinkCI (lua_State *L) { | |||
|       ci = next2;  /* continue */ | ||||
|     } | ||||
|   } | ||||
|   L->nCcalls -= L->nci;  /* adjust result */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** Called when 'getCcalls(L)' larger or equal to LUAI_MAXCCALLS. | ||||
| ** If equal, raises an overflow error. If value is larger than | ||||
| ** LUAI_MAXCCALLS (which means it is handling an overflow) but | ||||
| ** not much larger, does not report an error (to allow overflow | ||||
| ** handling to work). | ||||
| */ | ||||
| void luaE_checkcstack (lua_State *L) { | ||||
|   if (getCcalls(L) == LUAI_MAXCCALLS) | ||||
|     luaG_runerror(L, "C stack overflow"); | ||||
|   else if (getCcalls(L) >= (LUAI_MAXCCALLS / 10 * 11)) | ||||
|     luaD_throw(L, LUA_ERRERR);  /* error while handing stack error */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| LUAI_FUNC void luaE_incCstack (lua_State *L) { | ||||
|   L->nCcalls++; | ||||
|   if (unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) | ||||
|     luaE_checkcstack(L); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void stack_init (lua_State *L1, lua_State *L) { | ||||
|   int i; CallInfo *ci; | ||||
|   /* initialize stack array */ | ||||
|   L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, StackValue); | ||||
|   L1->stacksize = BASIC_STACK_SIZE; | ||||
|   for (i = 0; i < BASIC_STACK_SIZE; i++) | ||||
|   L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue); | ||||
|   for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++) | ||||
|     setnilvalue(s2v(L1->stack + i));  /* erase new stack */ | ||||
|   L1->top = L1->stack; | ||||
|   L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK; | ||||
|   L1->stack_last = L1->stack + BASIC_STACK_SIZE; | ||||
|   /* initialize first ci */ | ||||
|   ci = &L1->base_ci; | ||||
|   ci->next = ci->previous = NULL; | ||||
|  | @ -240,7 +205,7 @@ static void freestack (lua_State *L) { | |||
|   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 */ | ||||
|   luaM_freearray(L, L->stack, stacksize(L) + EXTRA_STACK);  /* free stack */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -290,7 +255,6 @@ static void preinit_thread (lua_State *L, global_State *g) { | |||
|   L->stack = NULL; | ||||
|   L->ci = NULL; | ||||
|   L->nci = 0; | ||||
|   L->stacksize = 0; | ||||
|   L->twups = L;  /* thread has no upvalues */ | ||||
|   L->errorJmp = NULL; | ||||
|   L->hook = NULL; | ||||
|  | @ -335,7 +299,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) { | |||
|   setthvalue2s(L, L->top, L1); | ||||
|   api_incr_top(L); | ||||
|   preinit_thread(L1, g); | ||||
|   L1->nCcalls = getCcalls(L); | ||||
|   L1->nCcalls = 0; | ||||
|   L1->hookmask = L->hookmask; | ||||
|   L1->basehookcount = L->basehookcount; | ||||
|   L1->hook = L->hook; | ||||
|  | @ -396,7 +360,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
|   preinit_thread(L, g); | ||||
|   g->allgc = obj2gco(L);  /* by now, only object is the main thread */ | ||||
|   L->next = NULL; | ||||
|   g->Cstacklimit = L->nCcalls = LUAI_MAXCSTACK + CSTACKERR; | ||||
|   L->nCcalls = 0; | ||||
|   incnny(L);  /* main thread is always non yieldable */ | ||||
|   g->frealloc = f; | ||||
|   g->ud = ud; | ||||
|  |  | |||
|  | @ -87,49 +87,13 @@ | |||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** About 'nCcalls': each thread in Lua (a lua_State) keeps a count of | ||||
| ** 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 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 an unknown amount | ||||
| ** of space (e.g., functions using an auxiliary buffer), calls | ||||
| ** to these functions add more than one to the count (see CSTACKCF). | ||||
| ** | ||||
| ** 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. | ||||
| ** About 'nCcalls':  This count has two parts: the lower 16 bits counts | ||||
| ** the number of recursive invocations in the C stack; the higher | ||||
| ** 16 bits counts the number of non-yieldable calls in the stack. | ||||
| ** (They are together so that we can change and save both with one | ||||
| ** instruction.) | ||||
| */ | ||||
| 
 | ||||
| /* 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) | ||||
| 
 | ||||
| 
 | ||||
| /* initial limit for the C-stack of threads */ | ||||
| #define CSTACKTHREAD	(2 * CSTACKERR) | ||||
| 
 | ||||
| 
 | ||||
| /* true if this thread does not have non-yieldable calls in the stack */ | ||||
| #define yieldable(L)		(((L)->nCcalls & 0xffff0000) == 0) | ||||
|  | @ -144,13 +108,8 @@ | |||
| /* Decrement the number of non-yieldable calls */ | ||||
| #define decnny(L)	((L)->nCcalls -= 0x10000) | ||||
| 
 | ||||
| /* 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 increment nCcalls */ | ||||
| #define decXCcalls(L)	((L)->nCcalls -= 0x10000 - CSTACKCF) | ||||
| 
 | ||||
| 
 | ||||
| /* Non-yieldable call increment */ | ||||
| #define nyci	(0x10000 | 1) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -168,12 +127,20 @@ struct lua_longjmp;  /* defined in ldo.c */ | |||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* extra stack space to handle TM calls and some other extras */ | ||||
| /*
 | ||||
| ** Extra stack space to handle TM calls and some other extras. This | ||||
| ** space is not included in 'stack_last'. It is used only to avoid stack | ||||
| ** checks, either because the element will be promptly popped or because | ||||
| ** there will be a stack check soon after the push. Function frames | ||||
| ** never use this extra space, so it does not need to be kept clean. | ||||
| */ | ||||
| #define EXTRA_STACK   5 | ||||
| 
 | ||||
| 
 | ||||
| #define BASIC_STACK_SIZE        (2*LUA_MINSTACK) | ||||
| 
 | ||||
| #define stacksize(th)	cast_int((th)->stack_last - (th)->stack) | ||||
| 
 | ||||
| 
 | ||||
| /* kinds of Garbage Collection */ | ||||
| #define KGC_INC		0	/* incremental gc */ | ||||
|  | @ -224,14 +191,15 @@ typedef struct CallInfo { | |||
| */ | ||||
| #define CIST_OAH	(1<<0)	/* original value of 'allowhook' */ | ||||
| #define CIST_C		(1<<1)	/* call is running a C function */ | ||||
| #define CIST_HOOKED	(1<<2)	/* call is running a debug hook */ | ||||
| #define CIST_YPCALL	(1<<3)	/* call is a yieldable protected call */ | ||||
| #define CIST_TAIL	(1<<4)	/* call was tail called */ | ||||
| #define CIST_HOOKYIELD	(1<<5)	/* last hook called yielded */ | ||||
| #define CIST_FIN	(1<<6)  /* call is running a finalizer */ | ||||
| #define CIST_TRAN	(1<<7)	/* 'ci' has transfer information */ | ||||
| #define CIST_FRESH	(1<<2)  /* call is on a fresh "luaV_execute" frame */ | ||||
| #define CIST_HOOKED	(1<<3)	/* call is running a debug hook */ | ||||
| #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_FIN	(1<<7)  /* call is running a finalizer */ | ||||
| #define CIST_TRAN	(1<<8)	/* 'ci' has transfer information */ | ||||
| #if defined(LUA_COMPAT_LT_LE) | ||||
| #define CIST_LEQ	(1<<8)  /* using __lt for __le */ | ||||
| #define CIST_LEQ	(1<<9)  /* using __lt for __le */ | ||||
| #endif | ||||
| 
 | ||||
| /* active function is a Lua function */ | ||||
|  | @ -296,7 +264,6 @@ typedef struct global_State { | |||
|   TString *strcache[STRCACHE_N][STRCACHE_M];  /* cache for strings in API */ | ||||
|   lua_WarnFunction warnf;  /* warning function */ | ||||
|   void *ud_warn;         /* auxiliary data to 'warnf' */ | ||||
|   unsigned int Cstacklimit;  /* current limit for the C stack */ | ||||
| } global_State; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -311,7 +278,7 @@ struct lua_State { | |||
|   StkId top;  /* first free slot in the stack */ | ||||
|   global_State *l_G; | ||||
|   CallInfo *ci;  /* call info for current function */ | ||||
|   StkId stack_last;  /* last free slot in the stack */ | ||||
|   StkId stack_last;  /* end of stack (last element + 1) */ | ||||
|   StkId stack;  /* stack base */ | ||||
|   UpVal *openupval;  /* list of open upvalues in this stack */ | ||||
|   GCObject *gclist; | ||||
|  | @ -320,9 +287,8 @@ struct lua_State { | |||
|   CallInfo base_ci;  /* CallInfo for first level (C calling Lua) */ | ||||
|   volatile lua_Hook hook; | ||||
|   ptrdiff_t errfunc;  /* current error handling function (stack index) */ | ||||
|   l_uint32 nCcalls;  /* number of allowed nested C calls - 'nci' */ | ||||
|   l_uint32 nCcalls;  /* number of nested (non-yieldable | C)  calls */ | ||||
|   int oldpc;  /* last pc traced */ | ||||
|   int stacksize; | ||||
|   int basehookcount; | ||||
|   int hookcount; | ||||
|   volatile l_signalT hookmask; | ||||
|  | @ -389,12 +355,11 @@ LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); | |||
| LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); | ||||
| LUAI_FUNC void luaE_freeCI (lua_State *L); | ||||
| LUAI_FUNC void luaE_shrinkCI (lua_State *L); | ||||
| LUAI_FUNC void luaE_enterCcall (lua_State *L); | ||||
| LUAI_FUNC void luaE_checkcstack (lua_State *L); | ||||
| LUAI_FUNC void luaE_incCstack (lua_State *L); | ||||
| LUAI_FUNC void luaE_warning (lua_State *L, const char *msg, int tocont); | ||||
| LUAI_FUNC void luaE_warnerror (lua_State *L, const char *where); | ||||
| 
 | ||||
| 
 | ||||
| #define luaE_exitCcall(L)	((L)->nCcalls++) | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
|  |  | |||
|  | @ -22,16 +22,6 @@ | |||
| #include "lstring.h" | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a long string to | ||||
| ** compute its hash | ||||
| */ | ||||
| #if !defined(LUAI_HASHLIMIT) | ||||
| #define LUAI_HASHLIMIT		5 | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** Maximum size for string table. | ||||
| */ | ||||
|  | @ -50,10 +40,9 @@ int luaS_eqlngstr (TString *a, TString *b) { | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| unsigned int luaS_hash (const char *str, size_t l, unsigned int seed, | ||||
|                         size_t step) { | ||||
| unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) { | ||||
|   unsigned int h = seed ^ cast_uint(l); | ||||
|   for (; l >= step; l -= step) | ||||
|   for (; l > 0; l--) | ||||
|     h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1])); | ||||
|   return h; | ||||
| } | ||||
|  | @ -63,8 +52,7 @@ unsigned int luaS_hashlongstr (TString *ts) { | |||
|   lua_assert(ts->tt == LUA_VLNGSTR); | ||||
|   if (ts->extra == 0) {  /* no hash? */ | ||||
|     size_t len = ts->u.lnglen; | ||||
|     size_t step = (len >> LUAI_HASHLIMIT) + 1; | ||||
|     ts->hash = luaS_hash(getstr(ts), len, ts->hash, step); | ||||
|     ts->hash = luaS_hash(getstr(ts), len, ts->hash); | ||||
|     ts->extra = 1;  /* now it has its hash */ | ||||
|   } | ||||
|   return ts->hash; | ||||
|  | @ -201,7 +189,7 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) { | |||
|   TString *ts; | ||||
|   global_State *g = G(L); | ||||
|   stringtable *tb = &g->strt; | ||||
|   unsigned int h = luaS_hash(str, l, g->seed, 1); | ||||
|   unsigned int h = luaS_hash(str, l, g->seed); | ||||
|   TString **list = &tb->hash[lmod(h, tb->size)]; | ||||
|   lua_assert(str != NULL);  /* otherwise 'memcmp'/'memcpy' are undefined */ | ||||
|   for (ts = *list; ts != NULL; ts = ts->u.hnext) { | ||||
|  |  | |||
|  | @ -41,8 +41,7 @@ | |||
| #define eqshrstr(a,b)	check_exp((a)->tt == LUA_VSHRSTR, (a) == (b)) | ||||
| 
 | ||||
| 
 | ||||
| LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, | ||||
|                                   unsigned int seed, size_t step); | ||||
| 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); | ||||
|  |  | |||
|  | @ -1365,7 +1365,6 @@ typedef union Ftypes { | |||
|   float f; | ||||
|   double d; | ||||
|   lua_Number n; | ||||
|   char buff[5 * sizeof(lua_Number)];  /* enough for any float type */ | ||||
| } Ftypes; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1535,12 +1534,10 @@ static void packint (luaL_Buffer *b, lua_Unsigned n, | |||
| ** Copy 'size' bytes from 'src' to 'dest', correcting endianness if | ||||
| ** given 'islittle' is different from native endianness. | ||||
| */ | ||||
| static void copywithendian (volatile char *dest, volatile const char *src, | ||||
| static void copywithendian (char *dest, const char *src, | ||||
|                             int size, int islittle) { | ||||
|   if (islittle == nativeendian.little) { | ||||
|     while (size-- != 0) | ||||
|       *(dest++) = *(src++); | ||||
|   } | ||||
|   if (islittle == nativeendian.little) | ||||
|     memcpy(dest, src, size); | ||||
|   else { | ||||
|     dest += size - 1; | ||||
|     while (size-- != 0) | ||||
|  | @ -1584,14 +1581,14 @@ static int str_pack (lua_State *L) { | |||
|         break; | ||||
|       } | ||||
|       case Kfloat: {  /* floating-point options */ | ||||
|         volatile Ftypes u; | ||||
|         Ftypes u; | ||||
|         char *buff = luaL_prepbuffsize(&b, size); | ||||
|         lua_Number n = luaL_checknumber(L, arg);  /* get argument */ | ||||
|         if (size == sizeof(u.f)) u.f = (float)n;  /* copy it into 'u' */ | ||||
|         else if (size == sizeof(u.d)) u.d = (double)n; | ||||
|         else u.n = n; | ||||
|         /* move 'u' to final result, correcting endianness if needed */ | ||||
|         copywithendian(buff, u.buff, size, h.islittle); | ||||
|         copywithendian(buff, (char *)&u, size, h.islittle); | ||||
|         luaL_addsize(&b, size); | ||||
|         break; | ||||
|       } | ||||
|  | @ -1717,9 +1714,9 @@ static int str_unpack (lua_State *L) { | |||
|         break; | ||||
|       } | ||||
|       case Kfloat: { | ||||
|         volatile Ftypes u; | ||||
|         Ftypes u; | ||||
|         lua_Number num; | ||||
|         copywithendian(u.buff, data + pos, size, h.islittle); | ||||
|         copywithendian((char *)&u, data + pos, size, h.islittle); | ||||
|         if (size == sizeof(u.f)) num = (lua_Number)u.f; | ||||
|         else if (size == sizeof(u.d)) num = (lua_Number)u.d; | ||||
|         else num = u.n; | ||||
|  | @ -1738,7 +1735,7 @@ static int str_unpack (lua_State *L) { | |||
|         break; | ||||
|       } | ||||
|       case Kzstr: { | ||||
|         size_t len = (int)strlen(data + pos); | ||||
|         size_t len = strlen(data + pos); | ||||
|         luaL_argcheck(L, pos + len < ld, 2, | ||||
|                          "unfinished string for format 'z'"); | ||||
|         lua_pushlstring(L, data + pos, len); | ||||
|  |  | |||
|  | @ -166,17 +166,30 @@ static Node *mainpositionTV (const Table *t, const TValue *key) { | |||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| ** Check whether key 'k1' is equal to the key in node 'n2'. | ||||
| ** This equality is raw, so there are no metamethods. Floats | ||||
| ** with integer values have been normalized, so integers cannot | ||||
| ** be equal to floats. It is assumed that 'eqshrstr' is simply | ||||
| ** pointer equality, so that short strings are handled in the | ||||
| ** default case. | ||||
| ** Check whether key 'k1' is equal to the key in node 'n2'. This | ||||
| ** equality is raw, so there are no metamethods. Floats with integer | ||||
| ** values have been normalized, so integers cannot be equal to | ||||
| ** floats. It is assumed that 'eqshrstr' is simply pointer equality, so | ||||
| ** that short strings are handled in the default case. | ||||
| ** A true 'deadok' means to accept dead keys as equal to their original | ||||
| ** values. All dead keys are compared in the default case, by pointer | ||||
| ** identity. (Only collectable objects can produce dead keys.) Note that | ||||
| ** dead long strings are also compared by identity. | ||||
| ** Once a key is dead, its corresponding value may be collected, and | ||||
| ** then another value can be created with the same address. If this | ||||
| ** other value is given to 'next', 'equalkey' will signal a false | ||||
| ** positive. In a regular traversal, this situation should never happen, | ||||
| ** as all keys given to 'next' came from the table itself, and therefore | ||||
| ** could not have been collected. Outside a regular traversal, we | ||||
| ** have garbage in, garbage out. What is relevant is that this false | ||||
| ** positive does not break anything.  (In particular, 'next' will return | ||||
| ** some other valid item on the table or nil.) | ||||
| */ | ||||
| static int equalkey (const TValue *k1, const Node *n2) { | ||||
|   if (rawtt(k1) != keytt(n2))  /* not the same variants? */ | ||||
| static int equalkey (const TValue *k1, const Node *n2, int deadok) { | ||||
|   if ((rawtt(k1) != keytt(n2)) &&  /* not the same variants? */ | ||||
|        !(deadok && keyisdead(n2) && iscollectable(k1))) | ||||
|    return 0;  /* cannot be same key */ | ||||
|   switch (ttypetag(k1)) { | ||||
|   switch (keytt(n2)) { | ||||
|     case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE: | ||||
|       return 1; | ||||
|     case LUA_VNUMINT: | ||||
|  | @ -187,7 +200,7 @@ static int equalkey (const TValue *k1, const Node *n2) { | |||
|       return pvalue(k1) == pvalueraw(keyval(n2)); | ||||
|     case LUA_VLCF: | ||||
|       return fvalue(k1) == fvalueraw(keyval(n2)); | ||||
|     case LUA_VLNGSTR: | ||||
|     case ctb(LUA_VLNGSTR): | ||||
|       return luaS_eqlngstr(tsvalue(k1), keystrval(n2)); | ||||
|     default: | ||||
|       return gcvalue(k1) == gcvalueraw(keyval(n2)); | ||||
|  | @ -251,11 +264,12 @@ static unsigned int setlimittosize (Table *t) { | |||
| /*
 | ||||
| ** "Generic" get version. (Not that generic: not valid for integers, | ||||
| ** which may be in array part, nor for floats with integral values.) | ||||
| ** See explanation about 'deadok' in function 'equalkey'. | ||||
| */ | ||||
| static const TValue *getgeneric (Table *t, const TValue *key) { | ||||
| static const TValue *getgeneric (Table *t, const TValue *key, int deadok) { | ||||
|   Node *n = mainpositionTV(t, key); | ||||
|   for (;;) {  /* check whether 'key' is somewhere in the chain */ | ||||
|     if (equalkey(key, n)) | ||||
|     if (equalkey(key, n, deadok)) | ||||
|       return gval(n);  /* that's it */ | ||||
|     else { | ||||
|       int nx = gnext(n); | ||||
|  | @ -292,7 +306,7 @@ static unsigned int findindex (lua_State *L, Table *t, TValue *key, | |||
|   if (i - 1u < asize)  /* is 'key' inside array part? */ | ||||
|     return i;  /* yes; that's the index */ | ||||
|   else { | ||||
|     const TValue *n = getgeneric(t, key); | ||||
|     const TValue *n = getgeneric(t, key, 1); | ||||
|     if (unlikely(isabstkey(n))) | ||||
|       luaG_runerror(L, "invalid key to 'next'");  /* key not found */ | ||||
|     i = cast_int(nodefromval(n) - gnode(t, 0));  /* key index in hash table */ | ||||
|  | @ -730,7 +744,7 @@ const TValue *luaH_getstr (Table *t, TString *key) { | |||
|   else {  /* for long strings, use generic case */ | ||||
|     TValue ko; | ||||
|     setsvalue(cast(lua_State *, NULL), &ko, key); | ||||
|     return getgeneric(t, &ko); | ||||
|     return getgeneric(t, &ko, 0); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
|  | @ -750,7 +764,7 @@ const TValue *luaH_get (Table *t, const TValue *key) { | |||
|       /* else... */ | ||||
|     }  /* FALLTHROUGH */ | ||||
|     default: | ||||
|       return getgeneric(t, key); | ||||
|       return getgeneric(t, key, 0); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ | |||
| 
 | ||||
| #define LUA_VERSION_MAJOR	"5" | ||||
| #define LUA_VERSION_MINOR	"4" | ||||
| #define LUA_VERSION_RELEASE	"1" | ||||
| #define LUA_VERSION_RELEASE	"2" | ||||
| 
 | ||||
| #define LUA_VERSION_NUM			504 | ||||
| #define LUA_VERSION_RELEASE_NUM		(LUA_VERSION_NUM * 100 + 0) | ||||
|  |  | |||
|  | @ -36,21 +36,6 @@ | |||
| ** ===================================================================== | ||||
| */ | ||||
| 
 | ||||
| /*
 | ||||
| @@ LUAI_MAXCSTACK defines the maximum depth for nested calls and | ||||
| ** also limits the maximum depth of other recursive algorithms in | ||||
| ** the implementation, such as syntactic analysis. A value too | ||||
| ** large may allow the interpreter to crash (C-stack overflow). | ||||
| ** The default value seems ok for regular machines, but may be | ||||
| ** too high for restricted hardware. | ||||
| ** The test file 'cstack.lua' may help finding a good limit. | ||||
| ** (It will crash with a limit too high.) | ||||
| */ | ||||
| #if !defined(LUAI_MAXCSTACK) | ||||
| #define LUAI_MAXCSTACK		2000 | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| @@ LUA_USE_C89 controls the use of non-ISO-C89 features. | ||||
| ** Define it if you want Lua to avoid the use of a few C99 features | ||||
|  |  | |||
|  | @ -229,7 +229,7 @@ static int forprep (lua_State *L, StkId ra) { | |||
|         count /= l_castS2U(-(step + 1)) + 1u; | ||||
|       } | ||||
|       /* store the counter in place of the limit (which won't be
 | ||||
|          needed anymore */ | ||||
|          needed anymore) */ | ||||
|       setivalue(plimit, l_castU2S(count)); | ||||
|     } | ||||
|   } | ||||
|  | @ -1092,15 +1092,11 @@ void luaV_finishOp (lua_State *L) { | |||
| #define ProtectNT(exp)  (savepc(L), (exp), updatetrap(ci)) | ||||
| 
 | ||||
| /*
 | ||||
| ** Protect code that will finish the loop (returns) or can only raise | ||||
| ** errors. (That is, it will not return to the interpreter main loop | ||||
| ** after changing the stack or hooks.) | ||||
| ** Protect code that can only raise errors. (That is, it cannnot change | ||||
| ** the stack or hooks.) | ||||
| */ | ||||
| #define halfProtect(exp)  (savestate(L,ci), (exp)) | ||||
| 
 | ||||
| /* idem, but without changing the stack */ | ||||
| #define halfProtectNT(exp)  (savepc(L), (exp)) | ||||
| 
 | ||||
| /* 'c' is the limit of live values in the stack */ | ||||
| #define checkGC(L,c)  \ | ||||
| 	{ luaC_condGC(L, (savepc(L), L->top = (c)), \ | ||||
|  | @ -1132,17 +1128,20 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| #if LUA_USE_JUMPTABLE | ||||
| #include "ljumptab.h" | ||||
| #endif | ||||
|  tailcall: | ||||
|  startfunc: | ||||
|   trap = L->hookmask; | ||||
|  returning:  /* trap already set */ | ||||
|   cl = clLvalue(s2v(ci->func)); | ||||
|   k = cl->p->k; | ||||
|   pc = ci->u.l.savedpc; | ||||
|   if (trap) { | ||||
|     if (cl->p->is_vararg) | ||||
|       trap = 0;  /* hooks will start after VARARGPREP instruction */ | ||||
|     else if (pc == cl->p->code)  /* first instruction (not resuming)? */ | ||||
|       luaD_hookcall(L, ci); | ||||
|     ci->u.l.trap = 1;  /* there may be other hooks */ | ||||
|     if (pc == cl->p->code) {  /* first instruction (not resuming)? */ | ||||
|       if (cl->p->is_vararg) | ||||
|         trap = 0;  /* hooks will start after VARARGPREP instruction */ | ||||
|       else  /* check 'call' hook */ | ||||
|         luaD_hookcall(L, ci); | ||||
|     } | ||||
|     ci->u.l.trap = 1;  /* assume trap is on, for now */ | ||||
|   } | ||||
|   base = ci->func + 1; | ||||
|   /* main loop of interpreter */ | ||||
|  | @ -1151,7 +1150,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
|     StkId ra;  /* instruction's A register */ | ||||
|     vmfetch(); | ||||
|     lua_assert(base == ci->func + 1); | ||||
|     lua_assert(base <= L->top && L->top < L->stack + L->stacksize); | ||||
|     lua_assert(base <= L->top && L->top < L->stack_last); | ||||
|     /* invalidate top for instructions not expecting it */ | ||||
|     lua_assert(isIT(i) || (cast_void(L->top = base), 1)); | ||||
|     vmdispatch (GET_OPCODE(i)) { | ||||
|  | @ -1606,24 +1605,32 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
|         vmbreak; | ||||
|       } | ||||
|       vmcase(OP_CALL) { | ||||
|         CallInfo *newci; | ||||
|         int b = GETARG_B(i); | ||||
|         int nresults = GETARG_C(i) - 1; | ||||
|         if (b != 0)  /* fixed number of arguments? */ | ||||
|           L->top = ra + b;  /* top signals number of arguments */ | ||||
|         /* else previous instruction set top */ | ||||
|         ProtectNT(luaD_call(L, ra, nresults)); | ||||
|         savepc(L);  /* in case of errors */ | ||||
|         if ((newci = luaD_precall(L, ra, nresults)) == NULL) | ||||
|           updatetrap(ci);  /* C call; nothing else to be done */ | ||||
|         else {  /* Lua call: run function in this same C frame */ | ||||
|           ci = newci; | ||||
|           ci->callstatus = 0;  /* call re-uses 'luaV_execute' */ | ||||
|           goto startfunc; | ||||
|         } | ||||
|         vmbreak; | ||||
|       } | ||||
|       vmcase(OP_TAILCALL) { | ||||
|         int b = GETARG_B(i);  /* number of arguments + 1 (function) */ | ||||
|         int nparams1 = GETARG_C(i); | ||||
|         /* delat is virtual 'func' - real 'func' (vararg functions) */ | ||||
|         /* delta is virtual 'func' - real 'func' (vararg functions) */ | ||||
|         int delta = (nparams1) ? ci->u.l.nextraargs + nparams1 : 0; | ||||
|         if (b != 0) | ||||
|           L->top = ra + b; | ||||
|         else  /* previous instruction set top */ | ||||
|           b = cast_int(L->top - ra); | ||||
|         savepc(ci);  /* some calls here can raise errors */ | ||||
|         savepc(ci);  /* several calls here can raise errors */ | ||||
|         if (TESTARG_k(i)) { | ||||
|           /* close upvalues from current call; the compiler ensures
 | ||||
|              that there are no to-be-closed variables here, so this | ||||
|  | @ -1637,16 +1644,17 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
|           checkstackGCp(L, 1, ra); | ||||
|         } | ||||
|         if (!ttisLclosure(s2v(ra))) {  /* C function? */ | ||||
|           luaD_call(L, ra, LUA_MULTRET);  /* call it */ | ||||
|           luaD_precall(L, ra, LUA_MULTRET);  /* call it */ | ||||
|           updatetrap(ci); | ||||
|           updatestack(ci);  /* stack may have been relocated */ | ||||
|           ci->func -= delta; | ||||
|           luaD_poscall(L, ci, cast_int(L->top - ra)); | ||||
|           return; | ||||
|           ci->func -= delta;  /* restore 'func' (if vararg) */ | ||||
|           luaD_poscall(L, ci, cast_int(L->top - ra));  /* finish caller */ | ||||
|           updatetrap(ci);  /* 'luaD_poscall' can change hooks */ | ||||
|           goto ret;  /* caller returns after the tail call */ | ||||
|         } | ||||
|         ci->func -= delta; | ||||
|         ci->func -= delta;  /* restore 'func' (if vararg) */ | ||||
|         luaD_pretailcall(L, ci, ra, b);  /* prepare call frame */ | ||||
|         goto tailcall; | ||||
|         goto startfunc;  /* execute the callee */ | ||||
|       } | ||||
|       vmcase(OP_RETURN) { | ||||
|         int n = GETARG_B(i) - 1;  /* number of results */ | ||||
|  | @ -1665,12 +1673,15 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
|           ci->func -= ci->u.l.nextraargs + nparams1; | ||||
|         L->top = ra + n;  /* set call for 'luaD_poscall' */ | ||||
|         luaD_poscall(L, ci, n); | ||||
|         return; | ||||
|         updatetrap(ci);  /* 'luaD_poscall' can change hooks */ | ||||
|         goto ret; | ||||
|       } | ||||
|       vmcase(OP_RETURN0) { | ||||
|         if (L->hookmask) { | ||||
|           L->top = ra; | ||||
|           halfProtectNT(luaD_poscall(L, ci, 0));  /* no hurry... */ | ||||
|           savepc(ci); | ||||
|           luaD_poscall(L, ci, 0);  /* no hurry... */ | ||||
|           trap = 1; | ||||
|         } | ||||
|         else {  /* do the 'poscall' here */ | ||||
|           int nres = ci->nresults; | ||||
|  | @ -1679,12 +1690,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
|           while (nres-- > 0) | ||||
|             setnilvalue(s2v(L->top++));  /* all results are nil */ | ||||
|         } | ||||
|         return; | ||||
|         goto ret; | ||||
|       } | ||||
|       vmcase(OP_RETURN1) { | ||||
|         if (L->hookmask) { | ||||
|           L->top = ra + 1; | ||||
|           halfProtectNT(luaD_poscall(L, ci, 1));  /* no hurry... */ | ||||
|           savepc(ci); | ||||
|           luaD_poscall(L, ci, 1);  /* no hurry... */ | ||||
|           trap = 1; | ||||
|         } | ||||
|         else {  /* do the 'poscall' here */ | ||||
|           int nres = ci->nresults; | ||||
|  | @ -1698,7 +1711,13 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
|               setnilvalue(s2v(L->top++)); | ||||
|           } | ||||
|         } | ||||
|         return; | ||||
|        ret:  /* return from a Lua function */ | ||||
|         if (ci->callstatus & CIST_FRESH) | ||||
|           return;  /* end this frame */ | ||||
|         else { | ||||
|           ci = ci->previous; | ||||
|           goto returning;  /* continue running caller in this frame */ | ||||
|         } | ||||
|       } | ||||
|       vmcase(OP_FORLOOP) { | ||||
|         if (ttisinteger(s2v(ra + 2))) {  /* integer loop? */ | ||||
|  |  | |||
|  | @ -54,6 +54,6 @@ win32 { | |||
|     RC_LANG = 0x0 | ||||
|     QMAKE_TARGET_COMPANY = "Syping" | ||||
|     QMAKE_TARGET_DESCRIPTION = "LuaEngine Library" | ||||
|     QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2018-2020 Syping" | ||||
|     QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2018-2021 Syping" | ||||
|     QMAKE_TARGET_PRODUCT = "LuaEngine" | ||||
| } | ||||
|  |  | |||
|  | @ -58,6 +58,6 @@ win32 { | |||
|     RC_LANG = 0x0 | ||||
|     QMAKE_TARGET_COMPANY = "Syping" | ||||
|     QMAKE_TARGET_DESCRIPTION = "LuaEngine Gui Library" | ||||
|     QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2018-2020 Syping" | ||||
|     QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2018-2021 Syping" | ||||
|     QMAKE_TARGET_PRODUCT = "LuaEngineGui" | ||||
| } | ||||
|  |  | |||
|  | @ -56,6 +56,6 @@ win32 { | |||
|     RC_LANG = 0x0 | ||||
|     QMAKE_TARGET_COMPANY = "Syping" | ||||
|     QMAKE_TARGET_DESCRIPTION = "LuaEngine I/O Library" | ||||
|     QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2019-2020 Syping" | ||||
|     QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2019-2021 Syping" | ||||
|     QMAKE_TARGET_PRODUCT = "LuaEngineIO" | ||||
| } | ||||
|  |  | |||
|  | @ -57,6 +57,6 @@ win32 { | |||
|     RC_LANG = 0x0 | ||||
|     QMAKE_TARGET_COMPANY = "Syping" | ||||
|     QMAKE_TARGET_DESCRIPTION = "LuaEngine Network Library" | ||||
|     QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2020 Syping" | ||||
|     QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2021 Syping" | ||||
|     QMAKE_TARGET_PRODUCT = "LuaEngineNetwork" | ||||
| } | ||||
|  |  | |||
|  | @ -56,6 +56,6 @@ win32 { | |||
|     RC_LANG = 0x0 | ||||
|     QMAKE_TARGET_COMPANY = "Syping" | ||||
|     QMAKE_TARGET_DESCRIPTION = "LuaEngine OS Library" | ||||
|     QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2019-2020 Syping" | ||||
|     QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2019-2021 Syping" | ||||
|     QMAKE_TARGET_PRODUCT = "LuaEngineOS" | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue