1866
|
1 /*
|
|
2 ** $Id: ldo.c,v 2.108 2012/10/01 14:05:04 roberto Exp $
|
|
3 ** Stack and Call structure of Lua
|
|
4 ** See Copyright Notice in lua.h
|
|
5 */
|
|
6
|
|
7
|
|
8 #include <setjmp.h>
|
|
9 #include <stdlib.h>
|
|
10 #include <string.h>
|
|
11
|
|
12 #define ldo_c
|
|
13 #define LUA_CORE
|
|
14
|
|
15 #include "lua.h"
|
|
16
|
|
17 #include "lapi.h"
|
|
18 #include "ldebug.h"
|
|
19 #include "ldo.h"
|
|
20 #include "lfunc.h"
|
|
21 #include "lgc.h"
|
|
22 #include "lmem.h"
|
|
23 #include "lobject.h"
|
|
24 #include "lopcodes.h"
|
|
25 #include "lparser.h"
|
|
26 #include "lstate.h"
|
|
27 #include "lstring.h"
|
|
28 #include "ltable.h"
|
|
29 #include "ltm.h"
|
|
30 #include "lundump.h"
|
|
31 #include "lvm.h"
|
|
32 #include "lzio.h"
|
|
33
|
|
34
|
|
35
|
|
36
|
|
37 /*
|
|
38 ** {======================================================
|
|
39 ** Error-recovery functions
|
|
40 ** =======================================================
|
|
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
|
|
75
|
|
76 /* chain list of long jump buffers */
|
|
77 struct lua_longjmp {
|
|
78 struct lua_longjmp *previous;
|
|
79 luai_jmpbuf b;
|
|
80 volatile int status; /* error code */
|
|
81 };
|
|
82
|
|
83
|
|
84 static void seterrorobj (lua_State *L, int errcode, StkId oldtop) {
|
|
85 switch (errcode) {
|
|
86 case LUA_ERRMEM: { /* memory error? */
|
|
87 setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */
|
|
88 break;
|
|
89 }
|
|
90 case LUA_ERRERR: {
|
|
91 setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
|
|
92 break;
|
|
93 }
|
|
94 default: {
|
|
95 setobjs2s(L, oldtop, L->top - 1); /* error message on current top */
|
|
96 break;
|
|
97 }
|
|
98 }
|
|
99 L->top = oldtop + 1;
|
|
100 }
|
|
101
|
|
102
|
|
103 l_noret luaD_throw (lua_State *L, int errcode) {
|
|
104 if (L->errorJmp) { /* thread has an error handler? */
|
|
105 L->errorJmp->status = errcode; /* set status */
|
|
106 LUAI_THROW(L, L->errorJmp); /* jump to it */
|
|
107 }
|
|
108 else { /* thread has no error handler */
|
|
109 L->status = cast_byte(errcode); /* mark it as dead */
|
|
110 if (G(L)->mainthread->errorJmp) { /* main thread has a handler? */
|
|
111 setobjs2s(L, G(L)->mainthread->top++, L->top - 1); /* copy error obj. */
|
|
112 luaD_throw(G(L)->mainthread, errcode); /* re-throw in main thread */
|
|
113 }
|
|
114 else { /* no handler at all; abort */
|
|
115 if (G(L)->panic) { /* panic function? */
|
|
116 lua_unlock(L);
|
|
117 G(L)->panic(L); /* call it (last chance to jump out) */
|
|
118 }
|
|
119 abort();
|
|
120 }
|
|
121 }
|
|
122 }
|
|
123
|
|
124
|
|
125 int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
|
|
126 unsigned short oldnCcalls = L->nCcalls;
|
|
127 struct lua_longjmp lj;
|
|
128 lj.status = LUA_OK;
|
|
129 lj.previous = L->errorJmp; /* chain new error handler */
|
|
130 L->errorJmp = &lj;
|
|
131 LUAI_TRY(L, &lj,
|
|
132 (*f)(L, ud);
|
|
133 );
|
|
134 L->errorJmp = lj.previous; /* restore old error handler */
|
|
135 L->nCcalls = oldnCcalls;
|
|
136 return lj.status;
|
|
137 }
|
|
138
|
|
139 /* }====================================================== */
|
|
140
|
|
141
|
|
142 static void correctstack (lua_State *L, TValue *oldstack) {
|
|
143 CallInfo *ci;
|
|
144 GCObject *up;
|
|
145 L->top = (L->top - oldstack) + L->stack;
|
|
146 for (up = L->openupval; up != NULL; up = up->gch.next)
|
|
147 gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;
|
|
148 for (ci = L->ci; ci != NULL; ci = ci->previous) {
|
|
149 ci->top = (ci->top - 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;
|
|
153 }
|
|
154 }
|
|
155
|
|
156
|
|
157 /* some space for error handling */
|
|
158 #define ERRORSTACKSIZE (LUAI_MAXSTACK + 200)
|
|
159
|
|
160
|
|
161 void luaD_reallocstack (lua_State *L, int newsize) {
|
|
162 TValue *oldstack = L->stack;
|
|
163 int lim = L->stacksize;
|
|
164 lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE);
|
|
165 lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK);
|
|
166 luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue);
|
|
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;
|
|
171 correctstack(L, oldstack);
|
|
172 }
|
|
173
|
|
174
|
|
175 void luaD_growstack (lua_State *L, int n) {
|
|
176 int size = L->stacksize;
|
|
177 if (size > LUAI_MAXSTACK) /* error after extra size? */
|
|
178 luaD_throw(L, LUA_ERRERR);
|
|
179 else {
|
|
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 }
|
|
191 }
|
|
192
|
|
193
|
|
194 static int stackinuse (lua_State *L) {
|
|
195 CallInfo *ci;
|
|
196 StkId lim = L->top;
|
|
197 for (ci = L->ci; ci != NULL; ci = ci->previous) {
|
|
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 */
|
|
202 }
|
|
203
|
|
204
|
|
205 void luaD_shrinkstack (lua_State *L) {
|
|
206 int inuse = stackinuse(L);
|
|
207 int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK;
|
|
208 if (goodsize > LUAI_MAXSTACK) goodsize = LUAI_MAXSTACK;
|
|
209 if (inuse > LUAI_MAXSTACK || /* handling stack overflow? */
|
|
210 goodsize >= L->stacksize) /* would grow instead of shrink? */
|
|
211 condmovestack(L); /* don't change stack (change only for debugging) */
|
|
212 else
|
|
213 luaD_reallocstack(L, goodsize); /* shrink it */
|
|
214 }
|
|
215
|
|
216
|
|
217 void luaD_hook (lua_State *L, int event, int line) {
|
|
218 lua_Hook hook = L->hook;
|
|
219 if (hook && L->allowhook) {
|
|
220 CallInfo *ci = L->ci;
|
|
221 ptrdiff_t top = savestack(L, L->top);
|
|
222 ptrdiff_t ci_top = savestack(L, ci->top);
|
|
223 lua_Debug ar;
|
|
224 ar.event = event;
|
|
225 ar.currentline = line;
|
|
226 ar.i_ci = ci;
|
|
227 luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
|
|
228 ci->top = L->top + LUA_MINSTACK;
|
|
229 lua_assert(ci->top <= L->stack_last);
|
|
230 L->allowhook = 0; /* cannot call hooks inside a hook */
|
|
231 ci->callstatus |= CIST_HOOKED;
|
|
232 lua_unlock(L);
|
|
233 (*hook)(L, &ar);
|
|
234 lua_lock(L);
|
|
235 lua_assert(!L->allowhook);
|
|
236 L->allowhook = 1;
|
|
237 ci->top = restorestack(L, ci_top);
|
|
238 L->top = restorestack(L, top);
|
|
239 ci->callstatus &= ~CIST_HOOKED;
|
|
240 }
|
|
241 }
|
|
242
|
|
243
|
|
244 static 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;
|
|
251 }
|
|
252 luaD_hook(L, hook, -1);
|
|
253 ci->u.l.savedpc--; /* correct 'pc' */
|
|
254 }
|
|
255
|
|
256
|
|
257 static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
|
|
258 int i;
|
|
259 int nfixargs = p->numparams;
|
|
260 StkId base, fixed;
|
|
261 lua_assert(actual >= nfixargs);
|
|
262 /* move fixed parameters to final position */
|
|
263 fixed = L->top - actual; /* first fixed argument */
|
|
264 base = L->top; /* final position of first argument */
|
|
265 for (i=0; i<nfixargs; i++) {
|
|
266 setobjs2s(L, L->top++, fixed + i);
|
|
267 setnilvalue(fixed + i);
|
|
268 }
|
|
269 return base;
|
|
270 }
|
|
271
|
|
272
|
|
273 static StkId tryfuncTM (lua_State *L, StkId func) {
|
|
274 const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL);
|
|
275 StkId p;
|
|
276 ptrdiff_t funcr = savestack(L, func);
|
|
277 if (!ttisfunction(tm))
|
|
278 luaG_typeerror(L, func, "call");
|
|
279 /* Open a hole inside the stack at `func' */
|
|
280 for (p = L->top; p > func; p--) setobjs2s(L, p, p-1);
|
|
281 incr_top(L);
|
|
282 func = restorestack(L, funcr); /* previous call may change stack */
|
|
283 setobj2s(L, func, tm); /* tag method is the new function to be called */
|
|
284 return func;
|
|
285 }
|
|
286
|
|
287
|
|
288
|
|
289 #define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L)))
|
|
290
|
|
291
|
|
292 /*
|
|
293 ** returns true if function has been executed (C function)
|
|
294 */
|
|
295 int luaD_precall (lua_State *L, StkId func, int nresults) {
|
|
296 lua_CFunction f;
|
|
297 CallInfo *ci;
|
|
298 int n; /* number of arguments (Lua) or returns (C) */
|
|
299 ptrdiff_t funcr = savestack(L, func);
|
|
300 switch (ttype(func)) {
|
|
301 case LUA_TLCF: /* light C function */
|
|
302 f = fvalue(func);
|
|
303 goto Cfunc;
|
|
304 case LUA_TCCL: { /* C closure */
|
|
305 f = clCvalue(func)->f;
|
|
306 Cfunc:
|
|
307 luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
|
|
308 ci = next_ci(L); /* now 'enter' new function */
|
|
309 ci->nresults = nresults;
|
|
310 ci->func = restorestack(L, funcr);
|
|
311 ci->top = L->top + LUA_MINSTACK;
|
|
312 lua_assert(ci->top <= L->stack_last);
|
|
313 ci->callstatus = 0;
|
|
314 luaC_checkGC(L); /* stack grow uses memory */
|
|
315 if (L->hookmask & LUA_MASKCALL)
|
|
316 luaD_hook(L, LUA_HOOKCALL, -1);
|
|
317 lua_unlock(L);
|
|
318 n = (*f)(L); /* do the actual call */
|
|
319 lua_lock(L);
|
|
320 api_checknelems(L, n);
|
|
321 luaD_poscall(L, L->top - n);
|
|
322 return 1;
|
|
323 }
|
|
324 case LUA_TLCL: { /* Lua function: prepare its call */
|
|
325 StkId base;
|
|
326 Proto *p = clLvalue(func)->p;
|
|
327 luaD_checkstack(L, p->maxstacksize);
|
|
328 func = restorestack(L, funcr);
|
|
329 n = cast_int(L->top - func) - 1; /* number of real arguments */
|
|
330 for (; n < p->numparams; n++)
|
|
331 setnilvalue(L->top++); /* complete missing arguments */
|
|
332 base = (!p->is_vararg) ? func + 1 : adjust_varargs(L, p, n);
|
|
333 ci = next_ci(L); /* now 'enter' new function */
|
|
334 ci->nresults = nresults;
|
|
335 ci->func = func;
|
|
336 ci->u.l.base = base;
|
|
337 ci->top = base + p->maxstacksize;
|
|
338 lua_assert(ci->top <= L->stack_last);
|
|
339 ci->u.l.savedpc = p->code; /* starting point */
|
|
340 ci->callstatus = CIST_LUA;
|
|
341 L->top = ci->top;
|
|
342 luaC_checkGC(L); /* stack grow uses memory */
|
|
343 if (L->hookmask & LUA_MASKCALL)
|
|
344 callhook(L, ci);
|
|
345 return 0;
|
|
346 }
|
|
347 default: { /* not a function */
|
|
348 func = tryfuncTM(L, func); /* retry with 'function' tag method */
|
|
349 return luaD_precall(L, func, nresults); /* now it must be a function */
|
|
350 }
|
|
351 }
|
|
352 }
|
|
353
|
|
354
|
|
355 int luaD_poscall (lua_State *L, StkId firstResult) {
|
|
356 StkId res;
|
|
357 int wanted, i;
|
|
358 CallInfo *ci = L->ci;
|
|
359 if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) {
|
|
360 if (L->hookmask & LUA_MASKRET) {
|
|
361 ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */
|
|
362 luaD_hook(L, LUA_HOOKRET, -1);
|
|
363 firstResult = restorestack(L, fr);
|
|
364 }
|
|
365 L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */
|
|
366 }
|
|
367 res = ci->func; /* res == final position of 1st result */
|
|
368 wanted = ci->nresults;
|
|
369 L->ci = ci = ci->previous; /* back to caller */
|
|
370 /* move results to correct place */
|
|
371 for (i = wanted; i != 0 && firstResult < L->top; i--)
|
|
372 setobjs2s(L, res++, firstResult++);
|
|
373 while (i-- > 0)
|
|
374 setnilvalue(res++);
|
|
375 L->top = res;
|
|
376 return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */
|
|
377 }
|
|
378
|
|
379
|
|
380 /*
|
|
381 ** Call a function (C or Lua). The function to be called is at *func.
|
|
382 ** The arguments are on the stack, right after the function.
|
|
383 ** When returns, all the results are on the stack, starting at the original
|
|
384 ** function position.
|
|
385 */
|
|
386 void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) {
|
|
387 if (++L->nCcalls >= LUAI_MAXCCALLS) {
|
|
388 if (L->nCcalls == LUAI_MAXCCALLS)
|
|
389 luaG_runerror(L, "C stack overflow");
|
|
390 else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
|
|
391 luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
|
|
392 }
|
|
393 if (!allowyield) L->nny++;
|
|
394 if (!luaD_precall(L, func, nResults)) /* is a Lua function? */
|
|
395 luaV_execute(L); /* call it */
|
|
396 if (!allowyield) L->nny--;
|
|
397 L->nCcalls--;
|
|
398 }
|
|
399
|
|
400
|
|
401 static void finishCcall (lua_State *L) {
|
|
402 CallInfo *ci = L->ci;
|
|
403 int n;
|
|
404 lua_assert(ci->u.c.k != NULL); /* must have a continuation */
|
|
405 lua_assert(L->nny == 0);
|
|
406 if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */
|
|
407 ci->callstatus &= ~CIST_YPCALL; /* finish 'lua_pcall' */
|
|
408 L->errfunc = ci->u.c.old_errfunc;
|
|
409 }
|
|
410 /* finish 'lua_callk'/'lua_pcall' */
|
|
411 adjustresults(L, ci->nresults);
|
|
412 /* call continuation function */
|
|
413 if (!(ci->callstatus & CIST_STAT)) /* no call status? */
|
|
414 ci->u.c.status = LUA_YIELD; /* 'default' status */
|
|
415 lua_assert(ci->u.c.status != LUA_OK);
|
|
416 ci->callstatus = (ci->callstatus & ~(CIST_YPCALL | CIST_STAT)) | CIST_YIELDED;
|
|
417 lua_unlock(L);
|
|
418 n = (*ci->u.c.k)(L);
|
|
419 lua_lock(L);
|
|
420 api_checknelems(L, n);
|
|
421 /* finish 'luaD_precall' */
|
|
422 luaD_poscall(L, L->top - n);
|
|
423 }
|
|
424
|
|
425
|
|
426 static void unroll (lua_State *L, void *ud) {
|
|
427 UNUSED(ud);
|
|
428 for (;;) {
|
|
429 if (L->ci == &L->base_ci) /* stack is empty? */
|
|
430 return; /* coroutine finished normally */
|
|
431 if (!isLua(L->ci)) /* C function? */
|
|
432 finishCcall(L);
|
|
433 else { /* Lua function */
|
|
434 luaV_finishOp(L); /* finish interrupted instruction */
|
|
435 luaV_execute(L); /* execute down to higher C 'boundary' */
|
|
436 }
|
|
437 }
|
|
438 }
|
|
439
|
|
440
|
|
441 /*
|
|
442 ** check whether thread has a suspended protected call
|
|
443 */
|
|
444 static CallInfo *findpcall (lua_State *L) {
|
|
445 CallInfo *ci;
|
|
446 for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */
|
|
447 if (ci->callstatus & CIST_YPCALL)
|
|
448 return ci;
|
|
449 }
|
|
450 return NULL; /* no pending pcall */
|
|
451 }
|
|
452
|
|
453
|
|
454 static int recover (lua_State *L, int status) {
|
|
455 StkId oldtop;
|
|
456 CallInfo *ci = findpcall(L);
|
|
457 if (ci == NULL) return 0; /* no recovery point */
|
|
458 /* "finish" luaD_pcall */
|
|
459 oldtop = restorestack(L, ci->extra);
|
|
460 luaF_close(L, oldtop);
|
|
461 seterrorobj(L, status, oldtop);
|
|
462 L->ci = ci;
|
|
463 L->allowhook = ci->u.c.old_allowhook;
|
|
464 L->nny = 0; /* should be zero to be yieldable */
|
|
465 luaD_shrinkstack(L);
|
|
466 L->errfunc = ci->u.c.old_errfunc;
|
|
467 ci->callstatus |= CIST_STAT; /* call has error status */
|
|
468 ci->u.c.status = status; /* (here it is) */
|
|
469 return 1; /* continue running the coroutine */
|
|
470 }
|
|
471
|
|
472
|
|
473 /*
|
|
474 ** signal an error in the call to 'resume', not in the execution of the
|
|
475 ** coroutine itself. (Such errors should not be handled by any coroutine
|
|
476 ** error handler and should not kill the coroutine.)
|
|
477 */
|
|
478 static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) {
|
|
479 L->top = firstArg; /* remove args from the stack */
|
|
480 setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */
|
|
481 api_incr_top(L);
|
|
482 luaD_throw(L, -1); /* jump back to 'lua_resume' */
|
|
483 }
|
|
484
|
|
485
|
|
486 /*
|
|
487 ** do the work for 'lua_resume' in protected mode
|
|
488 */
|
|
489 static void resume (lua_State *L, void *ud) {
|
|
490 int nCcalls = L->nCcalls;
|
|
491 StkId firstArg = cast(StkId, ud);
|
|
492 CallInfo *ci = L->ci;
|
|
493 if (nCcalls >= LUAI_MAXCCALLS)
|
|
494 resume_error(L, "C stack overflow", firstArg);
|
|
495 if (L->status == LUA_OK) { /* may be starting a coroutine */
|
|
496 if (ci != &L->base_ci) /* not in base level? */
|
|
497 resume_error(L, "cannot resume non-suspended coroutine", firstArg);
|
|
498 /* coroutine is in base level; start running it */
|
|
499 if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */
|
|
500 luaV_execute(L); /* call it */
|
|
501 }
|
|
502 else if (L->status != LUA_YIELD)
|
|
503 resume_error(L, "cannot resume dead coroutine", firstArg);
|
|
504 else { /* resuming from previous yield */
|
|
505 L->status = LUA_OK;
|
|
506 ci->func = restorestack(L, ci->extra);
|
|
507 if (isLua(ci)) /* yielded inside a hook? */
|
|
508 luaV_execute(L); /* just continue running Lua code */
|
|
509 else { /* 'common' yield */
|
|
510 if (ci->u.c.k != NULL) { /* does it have a continuation? */
|
|
511 int n;
|
|
512 ci->u.c.status = LUA_YIELD; /* 'default' status */
|
|
513 ci->callstatus |= CIST_YIELDED;
|
|
514 lua_unlock(L);
|
|
515 n = (*ci->u.c.k)(L); /* call continuation */
|
|
516 lua_lock(L);
|
|
517 api_checknelems(L, n);
|
|
518 firstArg = L->top - n; /* yield results come from continuation */
|
|
519 }
|
|
520 luaD_poscall(L, firstArg); /* finish 'luaD_precall' */
|
|
521 }
|
|
522 unroll(L, NULL);
|
|
523 }
|
|
524 lua_assert(nCcalls == L->nCcalls);
|
|
525 }
|
|
526
|
|
527
|
|
528 LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
|
|
529 int status;
|
|
530 lua_lock(L);
|
|
531 luai_userstateresume(L, nargs);
|
|
532 L->nCcalls = (from) ? from->nCcalls + 1 : 1;
|
|
533 L->nny = 0; /* allow yields */
|
|
534 api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
|
|
535 status = luaD_rawrunprotected(L, resume, L->top - nargs);
|
|
536 if (status == -1) /* error calling 'lua_resume'? */
|
|
537 status = LUA_ERRRUN;
|
|
538 else { /* yield or regular error */
|
|
539 while (status != LUA_OK && status != LUA_YIELD) { /* error? */
|
|
540 if (recover(L, status)) /* recover point? */
|
|
541 status = luaD_rawrunprotected(L, unroll, NULL); /* run continuation */
|
|
542 else { /* unrecoverable error */
|
|
543 L->status = cast_byte(status); /* mark thread as `dead' */
|
|
544 seterrorobj(L, status, L->top);
|
|
545 L->ci->top = L->top;
|
|
546 break;
|
|
547 }
|
|
548 }
|
|
549 lua_assert(status == L->status);
|
|
550 }
|
|
551 L->nny = 1; /* do not allow yields */
|
|
552 L->nCcalls--;
|
|
553 lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0));
|
|
554 lua_unlock(L);
|
|
555 return status;
|
|
556 }
|
|
557
|
|
558
|
|
559 LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k) {
|
|
560 CallInfo *ci = L->ci;
|
|
561 luai_userstateyield(L, nresults);
|
|
562 lua_lock(L);
|
|
563 api_checknelems(L, nresults);
|
|
564 if (L->nny > 0) {
|
|
565 if (L != G(L)->mainthread)
|
|
566 luaG_runerror(L, "attempt to yield across a C-call boundary");
|
|
567 else
|
|
568 luaG_runerror(L, "attempt to yield from outside a coroutine");
|
|
569 }
|
|
570 L->status = LUA_YIELD;
|
|
571 ci->extra = savestack(L, ci->func); /* save current 'func' */
|
|
572 if (isLua(ci)) { /* inside a hook? */
|
|
573 api_check(L, k == NULL, "hooks cannot continue after yielding");
|
|
574 }
|
|
575 else {
|
|
576 if ((ci->u.c.k = k) != NULL) /* is there a continuation? */
|
|
577 ci->u.c.ctx = ctx; /* save context */
|
|
578 ci->func = L->top - nresults - 1; /* protect stack below results */
|
|
579 luaD_throw(L, LUA_YIELD);
|
|
580 }
|
|
581 lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */
|
|
582 lua_unlock(L);
|
|
583 return 0; /* return to 'luaD_hook' */
|
|
584 }
|
|
585
|
|
586
|
|
587 int luaD_pcall (lua_State *L, Pfunc func, void *u,
|
|
588 ptrdiff_t old_top, ptrdiff_t ef) {
|
|
589 int status;
|
|
590 CallInfo *old_ci = L->ci;
|
|
591 lu_byte old_allowhooks = L->allowhook;
|
|
592 unsigned short old_nny = L->nny;
|
|
593 ptrdiff_t old_errfunc = L->errfunc;
|
|
594 L->errfunc = ef;
|
|
595 status = luaD_rawrunprotected(L, func, u);
|
|
596 if (status != LUA_OK) { /* an error occurred? */
|
|
597 StkId oldtop = restorestack(L, old_top);
|
|
598 luaF_close(L, oldtop); /* close possible pending closures */
|
|
599 seterrorobj(L, status, oldtop);
|
|
600 L->ci = old_ci;
|
|
601 L->allowhook = old_allowhooks;
|
|
602 L->nny = old_nny;
|
|
603 luaD_shrinkstack(L);
|
|
604 }
|
|
605 L->errfunc = old_errfunc;
|
|
606 return status;
|
|
607 }
|
|
608
|
|
609
|
|
610
|
|
611 /*
|
|
612 ** Execute a protected parser.
|
|
613 */
|
|
614 struct SParser { /* data to `f_parser' */
|
|
615 ZIO *z;
|
|
616 Mbuffer buff; /* dynamic structure used by the scanner */
|
|
617 Dyndata dyd; /* dynamic structures used by the parser */
|
|
618 const char *mode;
|
|
619 const char *name;
|
|
620 };
|
|
621
|
|
622
|
|
623 static void checkmode (lua_State *L, const char *mode, const char *x) {
|
|
624 if (mode && strchr(mode, x[0]) == NULL) {
|
|
625 luaO_pushfstring(L,
|
|
626 "attempt to load a %s chunk (mode is " LUA_QS ")", x, mode);
|
|
627 luaD_throw(L, LUA_ERRSYNTAX);
|
|
628 }
|
|
629 }
|
|
630
|
|
631
|
|
632 static void f_parser (lua_State *L, void *ud) {
|
|
633 int i;
|
|
634 Closure *cl;
|
|
635 struct SParser *p = cast(struct SParser *, ud);
|
|
636 int c = zgetc(p->z); /* read first character */
|
|
637 if (c == LUA_SIGNATURE[0]) {
|
|
638 checkmode(L, p->mode, "binary");
|
|
639 cl = luaU_undump(L, p->z, &p->buff, p->name);
|
|
640 }
|
|
641 else {
|
|
642 checkmode(L, p->mode, "text");
|
|
643 cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c);
|
|
644 }
|
|
645 lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues);
|
|
646 for (i = 0; i < cl->l.nupvalues; i++) { /* initialize upvalues */
|
|
647 UpVal *up = luaF_newupval(L);
|
|
648 cl->l.upvals[i] = up;
|
|
649 luaC_objbarrier(L, cl, up);
|
|
650 }
|
|
651 }
|
|
652
|
|
653
|
|
654 int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
|
|
655 const char *mode) {
|
|
656 struct SParser p;
|
|
657 int status;
|
|
658 L->nny++; /* cannot yield during parsing */
|
|
659 p.z = z; p.name = name; p.mode = mode;
|
|
660 p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0;
|
|
661 p.dyd.gt.arr = NULL; p.dyd.gt.size = 0;
|
|
662 p.dyd.label.arr = NULL; p.dyd.label.size = 0;
|
|
663 luaZ_initbuffer(L, &p.buff);
|
|
664 status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);
|
|
665 luaZ_freebuffer(L, &p.buff);
|
|
666 luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size);
|
|
667 luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size);
|
|
668 luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size);
|
|
669 L->nny--;
|
|
670 return status;
|
|
671 }
|
|
672
|
|
673
|