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