~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/lua/src/ldo.c

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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