]>
cvs.zerfleddert.de Git - proxmark3-svn/blob - liblua/ldo.c
   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 
  38 ** {====================================================== 
  39 ** Error-recovery functions 
  40 ** ======================================================= 
  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. 
  49 #if !defined(LUAI_THROW) 
  51 #if defined(__cplusplus) && !defined(LUA_USE_LONGJMP) 
  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 */ 
  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 
  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 
  76 /* chain list of long jump buffers */ 
  78   struct lua_longjmp 
*previous
; 
  80   volatile int status
;  /* error code */ 
  84 static void seterrorobj (lua_State 
*L
, int errcode
, StkId oldtop
) { 
  86     case LUA_ERRMEM
: {  /* memory error? */ 
  87       setsvalue2s(L
, oldtop
, G(L
)->memerrmsg
); /* reuse preregistered msg. */ 
  91       setsvalue2s(L
, oldtop
, luaS_newliteral(L
, "error in error handling")); 
  95       setobjs2s(L
, oldtop
, L
->top 
- 1);  /* error message on current top */ 
 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 */ 
 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 */ 
 114     else {  /* no handler at all; abort */ 
 115       if (G(L
)->panic
) {  /* panic function? */ 
 117         G(L
)->panic(L
);  /* call it (last chance to jump out) */ 
 125 int luaD_rawrunprotected (lua_State 
*L
, Pfunc f
, void *ud
) { 
 126   unsigned short oldnCcalls 
= L
->nCcalls
; 
 127   struct lua_longjmp lj
; 
 129   lj
.previous 
= L
->errorJmp
;  /* chain new error handler */ 
 134   L
->errorJmp 
= lj
.previous
;  /* restore old error handler */ 
 135   L
->nCcalls 
= oldnCcalls
; 
 139 /* }====================================================== */ 
 142 static void correctstack (lua_State 
*L
, TValue 
*oldstack
) { 
 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
; 
 152       ci
->u
.l
.base 
= (ci
->u
.l
.base 
- oldstack
) + L
->stack
; 
 157 /* some space for error handling */ 
 158 #define ERRORSTACKSIZE  (LUAI_MAXSTACK + 200) 
 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
); 
 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
); 
 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"); 
 189       luaD_reallocstack(L
, newsize
); 
 194 static int stackinuse (lua_State 
*L
) { 
 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
; 
 201   return cast_int(lim 
- L
->stack
) + 1;  /* part of stack in use */ 
 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) */ 
 213     luaD_reallocstack(L
, goodsize
);  /* shrink it */ 
 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
); 
 225     ar
.currentline 
= line
; 
 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
; 
 235     lua_assert(!L
->allowhook
); 
 237     ci
->top 
= restorestack(L
, ci_top
); 
 238     L
->top 
= restorestack(L
, top
); 
 239     ci
->callstatus 
&= ~CIST_HOOKED
; 
 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
; 
 252   luaD_hook(L
, hook
, -1); 
 253   ci
->u
.l
.savedpc
--;  /* correct 'pc' */ 
 257 static StkId 
adjust_varargs (lua_State 
*L
, Proto 
*p
, int actual
) { 
 259   int nfixargs 
= p
->numparams
; 
 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
); 
 273 static StkId 
tryfuncTM (lua_State 
*L
, StkId func
) { 
 274   const TValue 
*tm 
= luaT_gettmbyobj(L
, func
, TM_CALL
); 
 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); 
 282   func 
= restorestack(L
, funcr
);  /* previous call may change stack */ 
 283   setobj2s(L
, func
, tm
);  /* tag method is the new function to be called */ 
 289 #define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) 
 293 ** returns true if function has been executed (C function) 
 295 int luaD_precall (lua_State 
*L
, StkId func
, int nresults
) { 
 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 */ 
 304     case LUA_TCCL
: {  /* C closure */ 
 305       f 
= clCvalue(func
)->f
; 
 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
); 
 314       luaC_checkGC(L
);  /* stack grow uses memory */ 
 315       if (L
->hookmask 
& LUA_MASKCALL
) 
 316         luaD_hook(L
, LUA_HOOKCALL
, -1); 
 318       n 
= (*f
)(L
);  /* do the actual call */ 
 320       api_checknelems(L
, n
); 
 321       luaD_poscall(L
, L
->top 
- n
); 
 324     case LUA_TLCL
: {  /* Lua function: prepare its call */ 
 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
; 
 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
; 
 342       luaC_checkGC(L
);  /* stack grow uses memory */ 
 343       if (L
->hookmask 
& LUA_MASKCALL
) 
 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 */ 
 355 int luaD_poscall (lua_State 
*L
, StkId firstResult
) { 
 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
); 
 365     L
->oldpc 
= ci
->previous
->u
.l
.savedpc
;  /* 'oldpc' for caller function */ 
 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
++); 
 376   return (wanted 
- LUA_MULTRET
);  /* 0 iff wanted == LUA_MULTRET */ 
 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. 
 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 */ 
 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
--; 
 401 static void finishCcall (lua_State 
*L
) { 
 402   CallInfo 
*ci 
= L
->ci
; 
 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
; 
 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
; 
 420   api_checknelems(L
, n
); 
 421   /* finish 'luaD_precall' */ 
 422   luaD_poscall(L
, L
->top 
- n
); 
 426 static void unroll (lua_State 
*L
, void *ud
) { 
 429     if (L
->ci 
== &L
->base_ci
)  /* stack is empty? */ 
 430       return;  /* coroutine finished normally */ 
 431     if (!isLua(L
->ci
))  /* C function? */ 
 433     else {  /* Lua function */ 
 434       luaV_finishOp(L
);  /* finish interrupted instruction */ 
 435       luaV_execute(L
);  /* execute down to higher C 'boundary' */ 
 442 ** check whether thread has a suspended protected call 
 444 static CallInfo 
*findpcall (lua_State 
*L
) { 
 446   for (ci 
= L
->ci
; ci 
!= NULL
; ci 
= ci
->previous
) {  /* search for a pcall */ 
 447     if (ci
->callstatus 
& CIST_YPCALL
) 
 450   return NULL
;  /* no pending pcall */ 
 454 static int recover (lua_State 
*L
, int status
) { 
 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
); 
 463   L
->allowhook 
= ci
->u
.c
.old_allowhook
; 
 464   L
->nny 
= 0;  /* should be zero to be yieldable */ 
 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 */ 
 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.) 
 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 */ 
 482   luaD_throw(L
, -1);  /* jump back to 'lua_resume' */ 
 487 ** do the work for 'lua_resume' in protected mode 
 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 */ 
 502   else if (L
->status 
!= LUA_YIELD
) 
 503     resume_error(L
, "cannot resume dead coroutine", firstArg
); 
 504   else {  /* resuming from previous yield */ 
 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? */ 
 512         ci
->u
.c
.status 
= LUA_YIELD
;  /* 'default' status */ 
 513         ci
->callstatus 
|= CIST_YIELDED
; 
 515         n 
= (*ci
->u
.c
.k
)(L
);  /* call continuation */ 
 517         api_checknelems(L
, n
); 
 518         firstArg 
= L
->top 
- n
;  /* yield results come from continuation */ 
 520       luaD_poscall(L
, firstArg
);  /* finish 'luaD_precall' */ 
 524   lua_assert(nCcalls 
== L
->nCcalls
); 
 528 LUA_API 
int lua_resume (lua_State 
*L
, lua_State 
*from
, int nargs
) { 
 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'? */ 
 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
); 
 549     lua_assert(status 
== L
->status
); 
 551   L
->nny 
= 1;  /* do not allow yields */ 
 553   lua_assert(L
->nCcalls 
== ((from
) ? from
->nCcalls 
: 0)); 
 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
); 
 563   api_checknelems(L
, nresults
); 
 565     if (L 
!= G(L
)->mainthread
) 
 566       luaG_runerror(L
, "attempt to yield across a C-call boundary"); 
 568       luaG_runerror(L
, "attempt to yield from outside a coroutine"); 
 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"); 
 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
); 
 581   lua_assert(ci
->callstatus 
& CIST_HOOKED
);  /* must be inside a hook */ 
 583   return 0;  /* return to 'luaD_hook' */ 
 587 int luaD_pcall (lua_State 
*L
, Pfunc func
, void *u
, 
 588                 ptrdiff_t old_top
, ptrdiff_t ef
) { 
 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
; 
 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
); 
 601     L
->allowhook 
= old_allowhooks
; 
 605   L
->errfunc 
= old_errfunc
; 
 612 ** Execute a protected parser. 
 614 struct SParser 
{  /* data to `f_parser' */ 
 616   Mbuffer buff
;  /* dynamic structure used by the scanner */ 
 617   Dyndata dyd
;  /* dynamic structures used by the parser */ 
 623 static void checkmode (lua_State 
*L
, const char *mode
, const char *x
) { 
 624   if (mode 
&& strchr(mode
, x
[0]) == NULL
) { 
 626        "attempt to load a %s chunk (mode is " LUA_QS 
")", x
, mode
); 
 627     luaD_throw(L
, LUA_ERRSYNTAX
); 
 632 static void f_parser (lua_State 
*L
, void *ud
) { 
 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
); 
 642     checkmode(L
, p
->mode
, "text"); 
 643     cl 
= luaY_parser(L
, p
->z
, &p
->buff
, &p
->dyd
, p
->name
, c
); 
 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
); 
 654 int luaD_protectedparser (lua_State 
*L
, ZIO 
*z
, const char *name
, 
 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
);