summaryrefslogtreecommitdiff
path: root/apps/plugins/lua/ldo.c
diff options
context:
space:
mode:
authorRichard Quirk <richard.quirk@gmail.com>2014-03-19 19:31:31 +0100
committerMarcin Bukat <marcin.bukat@gmail.com>2014-04-02 20:31:54 +0200
commit36378988ad4059982742f05f5eb50580b456840a (patch)
treeee70be810d894566c5e351f21a1ebb79be742a85 /apps/plugins/lua/ldo.c
parent020f16a1c7d5bc9a302671cef03f56ac735e20c5 (diff)
downloadrockbox-36378988ad4059982742f05f5eb50580b456840a.tar.gz
rockbox-36378988ad4059982742f05f5eb50580b456840a.zip
Update lua plugin to 5.2.3
Prior to this patch the Lua plugin used version 5.1.4. This change reduces the number of modifications in the Lua source using some new defines and because the upstream source is now more flexible. Unless otherwise stated, l*.[ch] files are taken unmodified from the upstream lua-5.2.3. fscanf.c: file descriptors in rockbox are just ints, they are hidden behind a void* now so liolib requires less modifications. fscanf is updated to use void* too. getc.c: this is a new file required for getc implementation in lauxlib.c lauxlib.c: LoadF replaced FILE* with int, the rockbox file descriptor int are cast to FILE* (actually void* due to typedef). getc uses the PREFIX version. stdin is not used, as per 5.1.4. lbaselib.c: now uses strspn in the number parsing. print uses DEBUGF now rather than being commented out. lbitlib.c: use the built-in version from 5.2.3 rather than Reuben Thomas's external library. Backwards compatible and adds some new bit operations. ldo.c: the LUAI_THROW/TRY defines are now in the core lua code, so have been removed from rockconf.h liolib.c: here the implementation has changed to use the LStream from the original source, and cast the FILE* pointers to int. This has reduced the number of modifications from the upstream version. llex.c: the only change from upstream is to remove the locale include. lmathlib.c: updated from the 5.2.3 version and re-applied the changes that were made vs 5.1.4 for random numbers and to remove unsupported float functions. loadlib.c: upstream version, with the 5.1.4 changes for missing functions. lobject.c: upstream version, with ctype.h added and sprintf changed to snprintf. loslib.c: upstream version with locale.h removed and 5.1.4 changes for unsupportable functions. lstrlib.c: sprintf changed to snprintf. ltable.c: upstream with the hashnum function from 5.1.4 to avoid frexp in luai_hashnum. luaconf.h: updated to 5.2.3 version, restored relevant parts from the original 5.1.4 configuration. The COMPAT defines that are no longer available are not included. lundump.c: VERSION macro conflicts with the core Rockbox equivalent. rocklib.c: luaL_reg is no longer available, replaced by luaL_Reg equivalent. Moved checkboolean/optboolean functions to this file and out of core lua files. luaL_getn is no longer available, replaced by luaL_rawlen. luaL_register is deprecated, use the newlib/setfuncs replacements. rli_init has to be called before setting up the newlib to avoid overwriting the rb table. rocklib_aux.pl: use rli_checkboolean from rocklib.c. rocklua.c: new default bits library used, update the library loading code with idiomatic 5.2 code. strcspn.c: no longer needed, but strspn.c is required for strspn in lbaselib.c Change-Id: I0c7945c755f79083afe98ec117e1e8cf13de2651 Reviewed-on: http://gerrit.rockbox.org/774 Tested: Richard Quirk <richard.quirk@gmail.com> Reviewed-by: Marcin Bukat <marcin.bukat@gmail.com>
Diffstat (limited to 'apps/plugins/lua/ldo.c')
-rw-r--r--apps/plugins/lua/ldo.c671
1 files changed, 417 insertions, 254 deletions
diff --git a/apps/plugins/lua/ldo.c b/apps/plugins/lua/ldo.c
index f303c744c7..e9dd5fa951 100644
--- a/apps/plugins/lua/ldo.c
+++ b/apps/plugins/lua/ldo.c
@@ -1,11 +1,11 @@
1/* 1/*
2** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $ 2** $Id: ldo.c,v 2.108.1.3 2013/11/08 18:22:50 roberto Exp $
3** Stack and Call structure of Lua 3** Stack and Call structure of Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
6 6
7 7
8/* #include <setjmp.h> */ 8#include <setjmp.h>
9#include <stdlib.h> 9#include <stdlib.h>
10#include <string.h> 10#include <string.h>
11 11
@@ -14,6 +14,7 @@
14 14
15#include "lua.h" 15#include "lua.h"
16 16
17#include "lapi.h"
17#include "ldebug.h" 18#include "ldebug.h"
18#include "ldo.h" 19#include "ldo.h"
19#include "lfunc.h" 20#include "lfunc.h"
@@ -39,6 +40,38 @@
39** ======================================================= 40** =======================================================
40*/ 41*/
41 42
43/*
44** LUAI_THROW/LUAI_TRY define how Lua does exception handling. By
45** default, Lua handles errors with exceptions when compiling as
46** C++ code, with _longjmp/_setjmp when asked to use them, and with
47** longjmp/setjmp otherwise.
48*/
49#if !defined(LUAI_THROW)
50
51#if defined(__cplusplus) && !defined(LUA_USE_LONGJMP)
52/* C++ exceptions */
53#define LUAI_THROW(L,c) throw(c)
54#define LUAI_TRY(L,c,a) \
55 try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; }
56#define luai_jmpbuf int /* dummy variable */
57
58#elif defined(LUA_USE_ULONGJMP)
59/* in Unix, try _longjmp/_setjmp (more efficient) */
60#define LUAI_THROW(L,c) _longjmp((c)->b, 1)
61#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a }
62#define luai_jmpbuf jmp_buf
63
64#else
65/* default handling with long jumps */
66#define LUAI_THROW(L,c) longjmp((c)->b, 1)
67#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a }
68#define luai_jmpbuf jmp_buf
69
70#endif
71
72#endif
73
74
42 75
43/* chain list of long jump buffers */ 76/* chain list of long jump buffers */
44struct lua_longjmp { 77struct lua_longjmp {
@@ -48,18 +81,17 @@ struct lua_longjmp {
48}; 81};
49 82
50 83
51void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { 84static void seterrorobj (lua_State *L, int errcode, StkId oldtop) {
52 switch (errcode) { 85 switch (errcode) {
53 case LUA_ERRMEM: { 86 case LUA_ERRMEM: { /* memory error? */
54 setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG)); 87 setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */
55 break; 88 break;
56 } 89 }
57 case LUA_ERRERR: { 90 case LUA_ERRERR: {
58 setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); 91 setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
59 break; 92 break;
60 } 93 }
61 case LUA_ERRSYNTAX: 94 default: {
62 case LUA_ERRRUN: {
63 setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ 95 setobjs2s(L, oldtop, L->top - 1); /* error message on current top */
64 break; 96 break;
65 } 97 }
@@ -68,55 +100,39 @@ void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {
68} 100}
69 101
70 102
71static void restore_stack_limit (lua_State *L) { 103l_noret luaD_throw (lua_State *L, int errcode) {
72 lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); 104 if (L->errorJmp) { /* thread has an error handler? */
73 if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */ 105 L->errorJmp->status = errcode; /* set status */
74 int inuse = cast_int(L->ci - L->base_ci); 106 LUAI_THROW(L, L->errorJmp); /* jump to it */
75 if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */
76 luaD_reallocCI(L, LUAI_MAXCALLS);
77 } 107 }
78} 108 else { /* thread has no error handler */
79 109 L->status = cast_byte(errcode); /* mark it as dead */
80 110 if (G(L)->mainthread->errorJmp) { /* main thread has a handler? */
81static void resetstack (lua_State *L, int status) { 111 setobjs2s(L, G(L)->mainthread->top++, L->top - 1); /* copy error obj. */
82 L->ci = L->base_ci; 112 luaD_throw(G(L)->mainthread, errcode); /* re-throw in main thread */
83 L->base = L->ci->base; 113 }
84 luaF_close(L, L->base); /* close eventual pending closures */ 114 else { /* no handler at all; abort */
85 luaD_seterrorobj(L, status, L->base); 115 if (G(L)->panic) { /* panic function? */
86 L->nCcalls = L->baseCcalls; 116 lua_unlock(L);
87 L->allowhook = 1; 117 G(L)->panic(L); /* call it (last chance to jump out) */
88 restore_stack_limit(L); 118 }
89 L->errfunc = 0; 119 abort();
90 L->errorJmp = NULL;
91}
92
93
94void luaD_throw (lua_State *L, int errcode) {
95 if (L->errorJmp) {
96 L->errorJmp->status = errcode;
97 LUAI_THROW(L, L->errorJmp);
98 }
99 else {
100 L->status = cast_byte(errcode);
101 if (G(L)->panic) {
102 resetstack(L, errcode);
103 lua_unlock(L);
104 G(L)->panic(L);
105 } 120 }
106 exit(EXIT_FAILURE);
107 } 121 }
108} 122}
109 123
110 124
111int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { 125int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
126 unsigned short oldnCcalls = L->nCcalls;
112 struct lua_longjmp lj; 127 struct lua_longjmp lj;
113 lj.status = 0; 128 lj.status = LUA_OK;
114 lj.previous = L->errorJmp; /* chain new error handler */ 129 lj.previous = L->errorJmp; /* chain new error handler */
115 L->errorJmp = &lj; 130 L->errorJmp = &lj;
116 LUAI_TRY(L, &lj, 131 LUAI_TRY(L, &lj,
117 (*f)(L, ud); 132 (*f)(L, ud);
118 ); 133 );
119 L->errorJmp = lj.previous; /* restore old error handler */ 134 L->errorJmp = lj.previous; /* restore old error handler */
135 L->nCcalls = oldnCcalls;
120 return lj.status; 136 return lj.status;
121} 137}
122 138
@@ -129,112 +145,127 @@ static void correctstack (lua_State *L, TValue *oldstack) {
129 L->top = (L->top - oldstack) + L->stack; 145 L->top = (L->top - oldstack) + L->stack;
130 for (up = L->openupval; up != NULL; up = up->gch.next) 146 for (up = L->openupval; up != NULL; up = up->gch.next)
131 gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; 147 gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;
132 for (ci = L->base_ci; ci <= L->ci; ci++) { 148 for (ci = L->ci; ci != NULL; ci = ci->previous) {
133 ci->top = (ci->top - oldstack) + L->stack; 149 ci->top = (ci->top - oldstack) + L->stack;
134 ci->base = (ci->base - oldstack) + L->stack;
135 ci->func = (ci->func - oldstack) + L->stack; 150 ci->func = (ci->func - oldstack) + L->stack;
151 if (isLua(ci))
152 ci->u.l.base = (ci->u.l.base - oldstack) + L->stack;
136 } 153 }
137 L->base = (L->base - oldstack) + L->stack;
138} 154}
139 155
140 156
157/* some space for error handling */
158#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200)
159
160
141void luaD_reallocstack (lua_State *L, int newsize) { 161void luaD_reallocstack (lua_State *L, int newsize) {
142 TValue *oldstack = L->stack; 162 TValue *oldstack = L->stack;
143 int realsize = newsize + 1 + EXTRA_STACK; 163 int lim = L->stacksize;
144 lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); 164 lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE);
145 luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); 165 lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK);
146 L->stacksize = realsize; 166 luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue);
147 L->stack_last = L->stack+newsize; 167 for (; lim < newsize; lim++)
168 setnilvalue(L->stack + lim); /* erase new segment */
169 L->stacksize = newsize;
170 L->stack_last = L->stack + newsize - EXTRA_STACK;
148 correctstack(L, oldstack); 171 correctstack(L, oldstack);
149} 172}
150 173
151 174
152void luaD_reallocCI (lua_State *L, int newsize) { 175void luaD_growstack (lua_State *L, int n) {
153 CallInfo *oldci = L->base_ci; 176 int size = L->stacksize;
154 luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); 177 if (size > LUAI_MAXSTACK) /* error after extra size? */
155 L->size_ci = newsize; 178 luaD_throw(L, LUA_ERRERR);
156 L->ci = (L->ci - oldci) + L->base_ci; 179 else {
157 L->end_ci = L->base_ci + L->size_ci - 1; 180 int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK;
181 int newsize = 2 * size;
182 if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK;
183 if (newsize < needed) newsize = needed;
184 if (newsize > LUAI_MAXSTACK) { /* stack overflow? */
185 luaD_reallocstack(L, ERRORSTACKSIZE);
186 luaG_runerror(L, "stack overflow");
187 }
188 else
189 luaD_reallocstack(L, newsize);
190 }
158} 191}
159 192
160 193
161void luaD_growstack (lua_State *L, int n) { 194static int stackinuse (lua_State *L) {
162 if (n <= L->stacksize) /* double size is enough? */ 195 CallInfo *ci;
163 luaD_reallocstack(L, 2*L->stacksize); 196 StkId lim = L->top;
164 else 197 for (ci = L->ci; ci != NULL; ci = ci->previous) {
165 luaD_reallocstack(L, L->stacksize + n); 198 lua_assert(ci->top <= L->stack_last);
199 if (lim < ci->top) lim = ci->top;
200 }
201 return cast_int(lim - L->stack) + 1; /* part of stack in use */
166} 202}
167 203
168 204
169static CallInfo *growCI (lua_State *L) { 205void luaD_shrinkstack (lua_State *L) {
170 if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */ 206 int inuse = stackinuse(L);
171 luaD_throw(L, LUA_ERRERR); 207 int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK;
172 else { 208 if (goodsize > LUAI_MAXSTACK) goodsize = LUAI_MAXSTACK;
173 luaD_reallocCI(L, 2*L->size_ci); 209 if (inuse > LUAI_MAXSTACK || /* handling stack overflow? */
174 if (L->size_ci > LUAI_MAXCALLS) 210 goodsize >= L->stacksize) /* would grow instead of shrink? */
175 luaG_runerror(L, "stack overflow"); 211 condmovestack(L); /* don't change stack (change only for debugging) */
176 } 212 else
177 return ++L->ci; 213 luaD_reallocstack(L, goodsize); /* shrink it */
178} 214}
179 215
180 216
181void luaD_callhook (lua_State *L, int event, int line) { 217void luaD_hook (lua_State *L, int event, int line) {
182 lua_Hook hook = L->hook; 218 lua_Hook hook = L->hook;
183 if (hook && L->allowhook) { 219 if (hook && L->allowhook) {
220 CallInfo *ci = L->ci;
184 ptrdiff_t top = savestack(L, L->top); 221 ptrdiff_t top = savestack(L, L->top);
185 ptrdiff_t ci_top = savestack(L, L->ci->top); 222 ptrdiff_t ci_top = savestack(L, ci->top);
186 lua_Debug ar; 223 lua_Debug ar;
187 ar.event = event; 224 ar.event = event;
188 ar.currentline = line; 225 ar.currentline = line;
189 if (event == LUA_HOOKTAILRET) 226 ar.i_ci = ci;
190 ar.i_ci = 0; /* tail call; no debug information about it */
191 else
192 ar.i_ci = cast_int(L->ci - L->base_ci);
193 luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ 227 luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
194 L->ci->top = L->top + LUA_MINSTACK; 228 ci->top = L->top + LUA_MINSTACK;
195 lua_assert(L->ci->top <= L->stack_last); 229 lua_assert(ci->top <= L->stack_last);
196 L->allowhook = 0; /* cannot call hooks inside a hook */ 230 L->allowhook = 0; /* cannot call hooks inside a hook */
231 ci->callstatus |= CIST_HOOKED;
197 lua_unlock(L); 232 lua_unlock(L);
198 (*hook)(L, &ar); 233 (*hook)(L, &ar);
199 lua_lock(L); 234 lua_lock(L);
200 lua_assert(!L->allowhook); 235 lua_assert(!L->allowhook);
201 L->allowhook = 1; 236 L->allowhook = 1;
202 L->ci->top = restorestack(L, ci_top); 237 ci->top = restorestack(L, ci_top);
203 L->top = restorestack(L, top); 238 L->top = restorestack(L, top);
239 ci->callstatus &= ~CIST_HOOKED;
240 }
241}
242
243
244static void callhook (lua_State *L, CallInfo *ci) {
245 int hook = LUA_HOOKCALL;
246 ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */
247 if (isLua(ci->previous) &&
248 GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) {
249 ci->callstatus |= CIST_TAIL;
250 hook = LUA_HOOKTAILCALL;
204 } 251 }
252 luaD_hook(L, hook, -1);
253 ci->u.l.savedpc--; /* correct 'pc' */
205} 254}
206 255
207 256
208static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { 257static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
209 int i; 258 int i;
210 int nfixargs = p->numparams; 259 int nfixargs = p->numparams;
211 Table *htab = NULL;
212 StkId base, fixed; 260 StkId base, fixed;
213 for (; actual < nfixargs; ++actual) 261 lua_assert(actual >= nfixargs);
214 setnilvalue(L->top++);
215#if defined(LUA_COMPAT_VARARG)
216 if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */
217 int nvar = actual - nfixargs; /* number of extra arguments */
218 lua_assert(p->is_vararg & VARARG_HASARG);
219 luaC_checkGC(L);
220 htab = luaH_new(L, nvar, 1); /* create `arg' table */
221 for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */
222 setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);
223 /* store counter in field `n' */
224 setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
225 }
226#endif
227 /* move fixed parameters to final position */ 262 /* move fixed parameters to final position */
263 luaD_checkstack(L, p->maxstacksize); /* check again for new 'base' */
228 fixed = L->top - actual; /* first fixed argument */ 264 fixed = L->top - actual; /* first fixed argument */
229 base = L->top; /* final position of first argument */ 265 base = L->top; /* final position of first argument */
230 for (i=0; i<nfixargs; i++) { 266 for (i=0; i<nfixargs; i++) {
231 setobjs2s(L, L->top++, fixed+i); 267 setobjs2s(L, L->top++, fixed + i);
232 setnilvalue(fixed+i); 268 setnilvalue(fixed + i);
233 }
234 /* add `arg' parameter */
235 if (htab) {
236 sethvalue(L, L->top++, htab);
237 lua_assert(iswhite(obj2gco(htab)));
238 } 269 }
239 return base; 270 return base;
240} 271}
@@ -256,100 +287,93 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
256 287
257 288
258 289
259#define inc_ci(L) \ 290#define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L)))
260 ((L->ci == L->end_ci) ? growCI(L) : \
261 (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci))
262 291
263 292
293/*
294** returns true if function has been executed (C function)
295*/
264int luaD_precall (lua_State *L, StkId func, int nresults) { 296int luaD_precall (lua_State *L, StkId func, int nresults) {
265 LClosure *cl; 297 lua_CFunction f;
266 ptrdiff_t funcr; 298 CallInfo *ci;
267 if (!ttisfunction(func)) /* `func' is not a function? */ 299 int n; /* number of arguments (Lua) or returns (C) */
268 func = tryfuncTM(L, func); /* check the `function' tag method */ 300 ptrdiff_t funcr = savestack(L, func);
269 funcr = savestack(L, func); 301 switch (ttype(func)) {
270 cl = &clvalue(func)->l; 302 case LUA_TLCF: /* light C function */
271 L->ci->savedpc = L->savedpc; 303 f = fvalue(func);
272 if (!cl->isC) { /* Lua function? prepare its call */ 304 goto Cfunc;
273 CallInfo *ci; 305 case LUA_TCCL: { /* C closure */
274 StkId st, base; 306 f = clCvalue(func)->f;
275 Proto *p = cl->p; 307 Cfunc:
276 luaD_checkstack(L, p->maxstacksize); 308 luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
277 func = restorestack(L, funcr); 309 ci = next_ci(L); /* now 'enter' new function */
278 if (!p->is_vararg) { /* no varargs? */ 310 ci->nresults = nresults;
279 base = func + 1; 311 ci->func = restorestack(L, funcr);
280 if (L->top > base + p->numparams) 312 ci->top = L->top + LUA_MINSTACK;
281 L->top = base + p->numparams; 313 lua_assert(ci->top <= L->stack_last);
282 } 314 ci->callstatus = 0;
283 else { /* vararg function */ 315 luaC_checkGC(L); /* stack grow uses memory */
284 int nargs = cast_int(L->top - func) - 1; 316 if (L->hookmask & LUA_MASKCALL)
285 base = adjust_varargs(L, p, nargs); 317 luaD_hook(L, LUA_HOOKCALL, -1);
286 func = restorestack(L, funcr); /* previous call may change the stack */ 318 lua_unlock(L);
319 n = (*f)(L); /* do the actual call */
320 lua_lock(L);
321 api_checknelems(L, n);
322 luaD_poscall(L, L->top - n);
323 return 1;
287 } 324 }
288 ci = inc_ci(L); /* now `enter' new function */ 325 case LUA_TLCL: { /* Lua function: prepare its call */
289 ci->func = func; 326 StkId base;
290 L->base = ci->base = base; 327 Proto *p = clLvalue(func)->p;
291 ci->top = L->base + p->maxstacksize; 328 n = cast_int(L->top - func) - 1; /* number of real arguments */
292 lua_assert(ci->top <= L->stack_last); 329 luaD_checkstack(L, p->maxstacksize);
293 L->savedpc = p->code; /* starting point */ 330 for (; n < p->numparams; n++)
294 ci->tailcalls = 0; 331 setnilvalue(L->top++); /* complete missing arguments */
295 ci->nresults = nresults; 332 if (!p->is_vararg) {
296 for (st = L->top; st < ci->top; st++) 333 func = restorestack(L, funcr);
297 setnilvalue(st); 334 base = func + 1;
298 L->top = ci->top; 335 }
299 if (L->hookmask & LUA_MASKCALL) { 336 else {
300 L->savedpc++; /* hooks assume 'pc' is already incremented */ 337 base = adjust_varargs(L, p, n);
301 luaD_callhook(L, LUA_HOOKCALL, -1); 338 func = restorestack(L, funcr); /* previous call can change stack */
302 L->savedpc--; /* correct 'pc' */ 339 }
340 ci = next_ci(L); /* now 'enter' new function */
341 ci->nresults = nresults;
342 ci->func = func;
343 ci->u.l.base = base;
344 ci->top = base + p->maxstacksize;
345 lua_assert(ci->top <= L->stack_last);
346 ci->u.l.savedpc = p->code; /* starting point */
347 ci->callstatus = CIST_LUA;
348 L->top = ci->top;
349 luaC_checkGC(L); /* stack grow uses memory */
350 if (L->hookmask & LUA_MASKCALL)
351 callhook(L, ci);
352 return 0;
303 } 353 }
304 return PCRLUA; 354 default: { /* not a function */
305 } 355 func = tryfuncTM(L, func); /* retry with 'function' tag method */
306 else { /* if is a C function, call it */ 356 return luaD_precall(L, func, nresults); /* now it must be a function */
307 CallInfo *ci;
308 int n;
309 luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
310 ci = inc_ci(L); /* now `enter' new function */
311 ci->func = restorestack(L, funcr);
312 L->base = ci->base = ci->func + 1;
313 ci->top = L->top + LUA_MINSTACK;
314 lua_assert(ci->top <= L->stack_last);
315 ci->nresults = nresults;
316 if (L->hookmask & LUA_MASKCALL)
317 luaD_callhook(L, LUA_HOOKCALL, -1);
318 lua_unlock(L);
319 n = (*curr_func(L)->c.f)(L); /* do the actual call */
320 lua_lock(L);
321 if (n < 0) /* yielding? */
322 return PCRYIELD;
323 else {
324 luaD_poscall(L, L->top - n);
325 return PCRC;
326 } 357 }
327 } 358 }
328} 359}
329 360
330 361
331static StkId callrethooks (lua_State *L, StkId firstResult) {
332 ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */
333 luaD_callhook(L, LUA_HOOKRET, -1);
334 if (f_isLua(L->ci)) { /* Lua function? */
335 while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */
336 luaD_callhook(L, LUA_HOOKTAILRET, -1);
337 }
338 return restorestack(L, fr);
339}
340
341
342int luaD_poscall (lua_State *L, StkId firstResult) { 362int luaD_poscall (lua_State *L, StkId firstResult) {
343 StkId res; 363 StkId res;
344 int wanted, i; 364 int wanted, i;
345 CallInfo *ci; 365 CallInfo *ci = L->ci;
346 if (L->hookmask & LUA_MASKRET) 366 if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) {
347 firstResult = callrethooks(L, firstResult); 367 if (L->hookmask & LUA_MASKRET) {
348 ci = L->ci--; 368 ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */
369 luaD_hook(L, LUA_HOOKRET, -1);
370 firstResult = restorestack(L, fr);
371 }
372 L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */
373 }
349 res = ci->func; /* res == final position of 1st result */ 374 res = ci->func; /* res == final position of 1st result */
350 wanted = ci->nresults; 375 wanted = ci->nresults;
351 L->base = (ci - 1)->base; /* restore base */ 376 L->ci = ci = ci->previous; /* back to caller */
352 L->savedpc = (ci - 1)->savedpc; /* restore savedpc */
353 /* move results to correct place */ 377 /* move results to correct place */
354 for (i = wanted; i != 0 && firstResult < L->top; i--) 378 for (i = wanted; i != 0 && firstResult < L->top; i--)
355 setobjs2s(L, res++, firstResult++); 379 setobjs2s(L, res++, firstResult++);
@@ -365,112 +389,226 @@ int luaD_poscall (lua_State *L, StkId firstResult) {
365** The arguments are on the stack, right after the function. 389** The arguments are on the stack, right after the function.
366** When returns, all the results are on the stack, starting at the original 390** When returns, all the results are on the stack, starting at the original
367** function position. 391** function position.
368*/ 392*/
369void luaD_call (lua_State *L, StkId func, int nResults) { 393void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) {
370 if (++L->nCcalls >= LUAI_MAXCCALLS) { 394 if (++L->nCcalls >= LUAI_MAXCCALLS) {
371 if (L->nCcalls == LUAI_MAXCCALLS) 395 if (L->nCcalls == LUAI_MAXCCALLS)
372 luaG_runerror(L, "C stack overflow"); 396 luaG_runerror(L, "C stack overflow");
373 else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) 397 else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
374 luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ 398 luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
375 } 399 }
376 if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */ 400 if (!allowyield) L->nny++;
377 luaV_execute(L, 1); /* call it */ 401 if (!luaD_precall(L, func, nResults)) /* is a Lua function? */
402 luaV_execute(L); /* call it */
403 if (!allowyield) L->nny--;
378 L->nCcalls--; 404 L->nCcalls--;
379 luaC_checkGC(L);
380} 405}
381 406
382 407
383static void resume (lua_State *L, void *ud) { 408static void finishCcall (lua_State *L) {
384 StkId firstArg = cast(StkId, ud);
385 CallInfo *ci = L->ci; 409 CallInfo *ci = L->ci;
386 if (L->status == 0) { /* start coroutine? */ 410 int n;
387 lua_assert(ci == L->base_ci && firstArg > L->base); 411 lua_assert(ci->u.c.k != NULL); /* must have a continuation */
388 if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA) 412 lua_assert(L->nny == 0);
389 return; 413 if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */
414 ci->callstatus &= ~CIST_YPCALL; /* finish 'lua_pcall' */
415 L->errfunc = ci->u.c.old_errfunc;
390 } 416 }
391 else { /* resuming from previous yield */ 417 /* finish 'lua_callk'/'lua_pcall' */
392 lua_assert(L->status == LUA_YIELD); 418 adjustresults(L, ci->nresults);
393 L->status = 0; 419 /* call continuation function */
394 if (!f_isLua(ci)) { /* `common' yield? */ 420 if (!(ci->callstatus & CIST_STAT)) /* no call status? */
395 /* finish interrupted execution of `OP_CALL' */ 421 ci->u.c.status = LUA_YIELD; /* 'default' status */
396 lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL || 422 lua_assert(ci->u.c.status != LUA_OK);
397 GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL); 423 ci->callstatus = (ci->callstatus & ~(CIST_YPCALL | CIST_STAT)) | CIST_YIELDED;
398 if (luaD_poscall(L, firstArg)) /* complete it... */ 424 lua_unlock(L);
399 L->top = L->ci->top; /* and correct top if not multiple results */ 425 n = (*ci->u.c.k)(L);
426 lua_lock(L);
427 api_checknelems(L, n);
428 /* finish 'luaD_precall' */
429 luaD_poscall(L, L->top - n);
430}
431
432
433static void unroll (lua_State *L, void *ud) {
434 UNUSED(ud);
435 for (;;) {
436 if (L->ci == &L->base_ci) /* stack is empty? */
437 return; /* coroutine finished normally */
438 if (!isLua(L->ci)) /* C function? */
439 finishCcall(L);
440 else { /* Lua function */
441 luaV_finishOp(L); /* finish interrupted instruction */
442 luaV_execute(L); /* execute down to higher C 'boundary' */
400 } 443 }
401 else /* yielded inside a hook: just continue its execution */
402 L->base = L->ci->base;
403 } 444 }
404 luaV_execute(L, cast_int(L->ci - L->base_ci));
405} 445}
406 446
407 447
408static int resume_error (lua_State *L, const char *msg) { 448/*
409 L->top = L->ci->base; 449** check whether thread has a suspended protected call
410 setsvalue2s(L, L->top, luaS_new(L, msg)); 450*/
411 incr_top(L); 451static CallInfo *findpcall (lua_State *L) {
412 lua_unlock(L); 452 CallInfo *ci;
413 return LUA_ERRRUN; 453 for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */
454 if (ci->callstatus & CIST_YPCALL)
455 return ci;
456 }
457 return NULL; /* no pending pcall */
458}
459
460
461static int recover (lua_State *L, int status) {
462 StkId oldtop;
463 CallInfo *ci = findpcall(L);
464 if (ci == NULL) return 0; /* no recovery point */
465 /* "finish" luaD_pcall */
466 oldtop = restorestack(L, ci->extra);
467 luaF_close(L, oldtop);
468 seterrorobj(L, status, oldtop);
469 L->ci = ci;
470 L->allowhook = ci->u.c.old_allowhook;
471 L->nny = 0; /* should be zero to be yieldable */
472 luaD_shrinkstack(L);
473 L->errfunc = ci->u.c.old_errfunc;
474 ci->callstatus |= CIST_STAT; /* call has error status */
475 ci->u.c.status = status; /* (here it is) */
476 return 1; /* continue running the coroutine */
477}
478
479
480/*
481** signal an error in the call to 'resume', not in the execution of the
482** coroutine itself. (Such errors should not be handled by any coroutine
483** error handler and should not kill the coroutine.)
484*/
485static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) {
486 L->top = firstArg; /* remove args from the stack */
487 setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */
488 api_incr_top(L);
489 luaD_throw(L, -1); /* jump back to 'lua_resume' */
414} 490}
415 491
416 492
417LUA_API int lua_resume (lua_State *L, int nargs) { 493/*
494** do the work for 'lua_resume' in protected mode
495*/
496static void resume (lua_State *L, void *ud) {
497 int nCcalls = L->nCcalls;
498 StkId firstArg = cast(StkId, ud);
499 CallInfo *ci = L->ci;
500 if (nCcalls >= LUAI_MAXCCALLS)
501 resume_error(L, "C stack overflow", firstArg);
502 if (L->status == LUA_OK) { /* may be starting a coroutine */
503 if (ci != &L->base_ci) /* not in base level? */
504 resume_error(L, "cannot resume non-suspended coroutine", firstArg);
505 /* coroutine is in base level; start running it */
506 if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */
507 luaV_execute(L); /* call it */
508 }
509 else if (L->status != LUA_YIELD)
510 resume_error(L, "cannot resume dead coroutine", firstArg);
511 else { /* resuming from previous yield */
512 L->status = LUA_OK;
513 ci->func = restorestack(L, ci->extra);
514 if (isLua(ci)) /* yielded inside a hook? */
515 luaV_execute(L); /* just continue running Lua code */
516 else { /* 'common' yield */
517 if (ci->u.c.k != NULL) { /* does it have a continuation? */
518 int n;
519 ci->u.c.status = LUA_YIELD; /* 'default' status */
520 ci->callstatus |= CIST_YIELDED;
521 lua_unlock(L);
522 n = (*ci->u.c.k)(L); /* call continuation */
523 lua_lock(L);
524 api_checknelems(L, n);
525 firstArg = L->top - n; /* yield results come from continuation */
526 }
527 luaD_poscall(L, firstArg); /* finish 'luaD_precall' */
528 }
529 unroll(L, NULL);
530 }
531 lua_assert(nCcalls == L->nCcalls);
532}
533
534
535LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
418 int status; 536 int status;
537 int oldnny = L->nny; /* save 'nny' */
419 lua_lock(L); 538 lua_lock(L);
420 if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci))
421 return resume_error(L, "cannot resume non-suspended coroutine");
422 if (L->nCcalls >= LUAI_MAXCCALLS)
423 return resume_error(L, "C stack overflow");
424 luai_userstateresume(L, nargs); 539 luai_userstateresume(L, nargs);
425 lua_assert(L->errfunc == 0); 540 L->nCcalls = (from) ? from->nCcalls + 1 : 1;
426 L->baseCcalls = ++L->nCcalls; 541 L->nny = 0; /* allow yields */
542 api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
427 status = luaD_rawrunprotected(L, resume, L->top - nargs); 543 status = luaD_rawrunprotected(L, resume, L->top - nargs);
428 if (status != 0) { /* error? */ 544 if (status == -1) /* error calling 'lua_resume'? */
429 L->status = cast_byte(status); /* mark thread as `dead' */ 545 status = LUA_ERRRUN;
430 luaD_seterrorobj(L, status, L->top); 546 else { /* yield or regular error */
431 L->ci->top = L->top; 547 while (status != LUA_OK && status != LUA_YIELD) { /* error? */
432 } 548 if (recover(L, status)) /* recover point? */
433 else { 549 status = luaD_rawrunprotected(L, unroll, NULL); /* run continuation */
434 lua_assert(L->nCcalls == L->baseCcalls); 550 else { /* unrecoverable error */
435 status = L->status; 551 L->status = cast_byte(status); /* mark thread as `dead' */
552 seterrorobj(L, status, L->top);
553 L->ci->top = L->top;
554 break;
555 }
556 }
557 lua_assert(status == L->status);
436 } 558 }
437 --L->nCcalls; 559 L->nny = oldnny; /* restore 'nny' */
560 L->nCcalls--;
561 lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0));
438 lua_unlock(L); 562 lua_unlock(L);
439 return status; 563 return status;
440} 564}
441 565
442 566
443LUA_API int lua_yield (lua_State *L, int nresults) { 567LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k) {
568 CallInfo *ci = L->ci;
444 luai_userstateyield(L, nresults); 569 luai_userstateyield(L, nresults);
445 lua_lock(L); 570 lua_lock(L);
446 if (L->nCcalls > L->baseCcalls) 571 api_checknelems(L, nresults);
447 luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); 572 if (L->nny > 0) {
448 L->base = L->top - nresults; /* protect stack slots below */ 573 if (L != G(L)->mainthread)
574 luaG_runerror(L, "attempt to yield across a C-call boundary");
575 else
576 luaG_runerror(L, "attempt to yield from outside a coroutine");
577 }
449 L->status = LUA_YIELD; 578 L->status = LUA_YIELD;
579 ci->extra = savestack(L, ci->func); /* save current 'func' */
580 if (isLua(ci)) { /* inside a hook? */
581 api_check(L, k == NULL, "hooks cannot continue after yielding");
582 }
583 else {
584 if ((ci->u.c.k = k) != NULL) /* is there a continuation? */
585 ci->u.c.ctx = ctx; /* save context */
586 ci->func = L->top - nresults - 1; /* protect stack below results */
587 luaD_throw(L, LUA_YIELD);
588 }
589 lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */
450 lua_unlock(L); 590 lua_unlock(L);
451 return -1; 591 return 0; /* return to 'luaD_hook' */
452} 592}
453 593
454 594
455int luaD_pcall (lua_State *L, Pfunc func, void *u, 595int luaD_pcall (lua_State *L, Pfunc func, void *u,
456 ptrdiff_t old_top, ptrdiff_t ef) { 596 ptrdiff_t old_top, ptrdiff_t ef) {
457 int status; 597 int status;
458 unsigned short oldnCcalls = L->nCcalls; 598 CallInfo *old_ci = L->ci;
459 ptrdiff_t old_ci = saveci(L, L->ci);
460 lu_byte old_allowhooks = L->allowhook; 599 lu_byte old_allowhooks = L->allowhook;
600 unsigned short old_nny = L->nny;
461 ptrdiff_t old_errfunc = L->errfunc; 601 ptrdiff_t old_errfunc = L->errfunc;
462 L->errfunc = ef; 602 L->errfunc = ef;
463 status = luaD_rawrunprotected(L, func, u); 603 status = luaD_rawrunprotected(L, func, u);
464 if (status != 0) { /* an error occurred? */ 604 if (status != LUA_OK) { /* an error occurred? */
465 StkId oldtop = restorestack(L, old_top); 605 StkId oldtop = restorestack(L, old_top);
466 luaF_close(L, oldtop); /* close eventual pending closures */ 606 luaF_close(L, oldtop); /* close possible pending closures */
467 luaD_seterrorobj(L, status, oldtop); 607 seterrorobj(L, status, oldtop);
468 L->nCcalls = oldnCcalls; 608 L->ci = old_ci;
469 L->ci = restoreci(L, old_ci);
470 L->base = L->ci->base;
471 L->savedpc = L->ci->savedpc;
472 L->allowhook = old_allowhooks; 609 L->allowhook = old_allowhooks;
473 restore_stack_limit(L); 610 L->nny = old_nny;
611 luaD_shrinkstack(L);
474 } 612 }
475 L->errfunc = old_errfunc; 613 L->errfunc = old_errfunc;
476 return status; 614 return status;
@@ -483,35 +621,60 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u,
483*/ 621*/
484struct SParser { /* data to `f_parser' */ 622struct SParser { /* data to `f_parser' */
485 ZIO *z; 623 ZIO *z;
486 Mbuffer buff; /* buffer to be used by the scanner */ 624 Mbuffer buff; /* dynamic structure used by the scanner */
625 Dyndata dyd; /* dynamic structures used by the parser */
626 const char *mode;
487 const char *name; 627 const char *name;
488}; 628};
489 629
630
631static void checkmode (lua_State *L, const char *mode, const char *x) {
632 if (mode && strchr(mode, x[0]) == NULL) {
633 luaO_pushfstring(L,
634 "attempt to load a %s chunk (mode is " LUA_QS ")", x, mode);
635 luaD_throw(L, LUA_ERRSYNTAX);
636 }
637}
638
639
490static void f_parser (lua_State *L, void *ud) { 640static void f_parser (lua_State *L, void *ud) {
491 int i; 641 int i;
492 Proto *tf;
493 Closure *cl; 642 Closure *cl;
494 struct SParser *p = cast(struct SParser *, ud); 643 struct SParser *p = cast(struct SParser *, ud);
495 int c = luaZ_lookahead(p->z); 644 int c = zgetc(p->z); /* read first character */
496 luaC_checkGC(L); 645 if (c == LUA_SIGNATURE[0]) {
497 tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, 646 checkmode(L, p->mode, "binary");
498 &p->buff, p->name); 647 cl = luaU_undump(L, p->z, &p->buff, p->name);
499 cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); 648 }
500 cl->l.p = tf; 649 else {
501 for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */ 650 checkmode(L, p->mode, "text");
502 cl->l.upvals[i] = luaF_newupval(L); 651 cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c);
503 setclvalue(L, L->top, cl); 652 }
504 incr_top(L); 653 lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues);
654 for (i = 0; i < cl->l.nupvalues; i++) { /* initialize upvalues */
655 UpVal *up = luaF_newupval(L);
656 cl->l.upvals[i] = up;
657 luaC_objbarrier(L, cl, up);
658 }
505} 659}
506 660
507 661
508int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) { 662int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
663 const char *mode) {
509 struct SParser p; 664 struct SParser p;
510 int status; 665 int status;
511 p.z = z; p.name = name; 666 L->nny++; /* cannot yield during parsing */
667 p.z = z; p.name = name; p.mode = mode;
668 p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0;
669 p.dyd.gt.arr = NULL; p.dyd.gt.size = 0;
670 p.dyd.label.arr = NULL; p.dyd.label.size = 0;
512 luaZ_initbuffer(L, &p.buff); 671 luaZ_initbuffer(L, &p.buff);
513 status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); 672 status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);
514 luaZ_freebuffer(L, &p.buff); 673 luaZ_freebuffer(L, &p.buff);
674 luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size);
675 luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size);
676 luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size);
677 L->nny--;
515 return status; 678 return status;
516} 679}
517 680