Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation/src/lua/ldo.c @ 2623

Last change on this file since 2623 was 1810, checked in by rgrieder, 16 years ago

merged ceguilua branch back to trunk

  • Property svn:eol-style set to native
File size: 14.5 KB
Line 
1/*
2** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 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 "ldebug.h"
18#include "ldo.h"
19#include "lfunc.h"
20#include "lgc.h"
21#include "lmem.h"
22#include "lobject.h"
23#include "lopcodes.h"
24#include "lparser.h"
25#include "lstate.h"
26#include "lstring.h"
27#include "ltable.h"
28#include "ltm.h"
29#include "lundump.h"
30#include "lvm.h"
31#include "lzio.h"
32
33
34
35
36/*
37** {======================================================
38** Error-recovery functions
39** =======================================================
40*/
41
42
43/* chain list of long jump buffers */
44struct lua_longjmp {
45  struct lua_longjmp *previous;
46  luai_jmpbuf b;
47  volatile int status;  /* error code */
48};
49
50
51void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {
52  switch (errcode) {
53    case LUA_ERRMEM: {
54      setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG));
55      break;
56    }
57    case LUA_ERRERR: {
58      setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
59      break;
60    }
61    case LUA_ERRSYNTAX:
62    case LUA_ERRRUN: {
63      setobjs2s(L, oldtop, L->top - 1);  /* error message on current top */
64      break;
65    }
66  }
67  L->top = oldtop + 1;
68}
69
70
71static void restore_stack_limit (lua_State *L) {
72  lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);
73  if (L->size_ci > LUAI_MAXCALLS) {  /* there was an overflow? */
74    int inuse = cast_int(L->ci - L->base_ci);
75    if (inuse + 1 < LUAI_MAXCALLS)  /* can `undo' overflow? */
76      luaD_reallocCI(L, LUAI_MAXCALLS);
77  }
78}
79
80
81static void resetstack (lua_State *L, int status) {
82  L->ci = L->base_ci;
83  L->base = L->ci->base;
84  luaF_close(L, L->base);  /* close eventual pending closures */
85  luaD_seterrorobj(L, status, L->base);
86  L->nCcalls = L->baseCcalls;
87  L->allowhook = 1;
88  restore_stack_limit(L);
89  L->errfunc = 0;
90  L->errorJmp = NULL;
91}
92
93
94void luaD_throw (lua_State *L, int errcode) {
95  if (L->errorJmp) {
96    L->errorJmp->status = errcode;
97    LUAI_THROW(L, L->errorJmp);
98  }
99  else {
100    L->status = cast_byte(errcode);
101    if (G(L)->panic) {
102      resetstack(L, errcode);
103      lua_unlock(L);
104      G(L)->panic(L);
105    }
106    exit(EXIT_FAILURE);
107  }
108}
109
110
111int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
112  struct lua_longjmp lj;
113  lj.status = 0;
114  lj.previous = L->errorJmp;  /* chain new error handler */
115  L->errorJmp = &lj;
116  LUAI_TRY(L, &lj,
117    (*f)(L, ud);
118  );
119  L->errorJmp = lj.previous;  /* restore old error handler */
120  return lj.status;
121}
122
123/* }====================================================== */
124
125
126static void correctstack (lua_State *L, TValue *oldstack) {
127  CallInfo *ci;
128  GCObject *up;
129  L->top = (L->top - oldstack) + L->stack;
130  for (up = L->openupval; up != NULL; up = up->gch.next)
131    gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;
132  for (ci = L->base_ci; ci <= L->ci; ci++) {
133    ci->top = (ci->top - oldstack) + L->stack;
134    ci->base = (ci->base - oldstack) + L->stack;
135    ci->func = (ci->func - oldstack) + L->stack;
136  }
137  L->base = (L->base - oldstack) + L->stack;
138}
139
140
141void luaD_reallocstack (lua_State *L, int newsize) {
142  TValue *oldstack = L->stack;
143  int realsize = newsize + 1 + EXTRA_STACK;
144  lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);
145  luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue);
146  L->stacksize = realsize;
147  L->stack_last = L->stack+newsize;
148  correctstack(L, oldstack);
149}
150
151
152void luaD_reallocCI (lua_State *L, int newsize) {
153  CallInfo *oldci = L->base_ci;
154  luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);
155  L->size_ci = newsize;
156  L->ci = (L->ci - oldci) + L->base_ci;
157  L->end_ci = L->base_ci + L->size_ci - 1;
158}
159
160
161void luaD_growstack (lua_State *L, int n) {
162  if (n <= L->stacksize)  /* double size is enough? */
163    luaD_reallocstack(L, 2*L->stacksize);
164  else
165    luaD_reallocstack(L, L->stacksize + n);
166}
167
168
169static CallInfo *growCI (lua_State *L) {
170  if (L->size_ci > LUAI_MAXCALLS)  /* overflow while handling overflow? */
171    luaD_throw(L, LUA_ERRERR);
172  else {
173    luaD_reallocCI(L, 2*L->size_ci);
174    if (L->size_ci > LUAI_MAXCALLS)
175      luaG_runerror(L, "stack overflow");
176  }
177  return ++L->ci;
178}
179
180
181void luaD_callhook (lua_State *L, int event, int line) {
182  lua_Hook hook = L->hook;
183  if (hook && L->allowhook) {
184    ptrdiff_t top = savestack(L, L->top);
185    ptrdiff_t ci_top = savestack(L, L->ci->top);
186    lua_Debug ar;
187    ar.event = event;
188    ar.currentline = line;
189    if (event == LUA_HOOKTAILRET)
190      ar.i_ci = 0;  /* tail call; no debug information about it */
191    else
192      ar.i_ci = cast_int(L->ci - L->base_ci);
193    luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */
194    L->ci->top = L->top + LUA_MINSTACK;
195    lua_assert(L->ci->top <= L->stack_last);
196    L->allowhook = 0;  /* cannot call hooks inside a hook */
197    lua_unlock(L);
198    (*hook)(L, &ar);
199    lua_lock(L);
200    lua_assert(!L->allowhook);
201    L->allowhook = 1;
202    L->ci->top = restorestack(L, ci_top);
203    L->top = restorestack(L, top);
204  }
205}
206
207
208static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
209  int i;
210  int nfixargs = p->numparams;
211  Table *htab = NULL;
212  StkId base, fixed;
213  for (; actual < nfixargs; ++actual)
214    setnilvalue(L->top++);
215#if defined(LUA_COMPAT_VARARG)
216  if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */
217    int nvar = actual - nfixargs;  /* number of extra arguments */
218    lua_assert(p->is_vararg & VARARG_HASARG);
219    luaC_checkGC(L);
220    htab = luaH_new(L, nvar, 1);  /* create `arg' table */
221    for (i=0; i<nvar; i++)  /* put extra arguments into `arg' table */
222      setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);
223    /* store counter in field `n' */
224    setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
225  }
226#endif
227  /* move fixed parameters to final position */
228  fixed = L->top - actual;  /* first fixed argument */
229  base = L->top;  /* final position of first argument */
230  for (i=0; i<nfixargs; i++) {
231    setobjs2s(L, L->top++, fixed+i);
232    setnilvalue(fixed+i);
233  }
234  /* add `arg' parameter */
235  if (htab) {
236    sethvalue(L, L->top++, htab);
237    lua_assert(iswhite(obj2gco(htab)));
238  }
239  return base;
240}
241
242
243static StkId tryfuncTM (lua_State *L, StkId func) {
244  const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL);
245  StkId p;
246  ptrdiff_t funcr = savestack(L, func);
247  if (!ttisfunction(tm))
248    luaG_typeerror(L, func, "call");
249  /* Open a hole inside the stack at `func' */
250  for (p = L->top; p > func; p--) setobjs2s(L, p, p-1);
251  incr_top(L);
252  func = restorestack(L, funcr);  /* previous call may change stack */
253  setobj2s(L, func, tm);  /* tag method is the new function to be called */
254  return func;
255}
256
257
258
259#define inc_ci(L) \
260  ((L->ci == L->end_ci) ? growCI(L) : \
261   (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci))
262
263
264int luaD_precall (lua_State *L, StkId func, int nresults) {
265  LClosure *cl;
266  ptrdiff_t funcr;
267  if (!ttisfunction(func)) /* `func' is not a function? */
268    func = tryfuncTM(L, func);  /* check the `function' tag method */
269  funcr = savestack(L, func);
270  cl = &clvalue(func)->l;
271  L->ci->savedpc = L->savedpc;
272  if (!cl->isC) {  /* Lua function? prepare its call */
273    CallInfo *ci;
274    StkId st, base;
275    Proto *p = cl->p;
276    luaD_checkstack(L, p->maxstacksize);
277    func = restorestack(L, funcr);
278    if (!p->is_vararg) {  /* no varargs? */
279      base = func + 1;
280      if (L->top > base + p->numparams)
281        L->top = base + p->numparams;
282    }
283    else {  /* vararg function */
284      int nargs = cast_int(L->top - func) - 1;
285      base = adjust_varargs(L, p, nargs);
286      func = restorestack(L, funcr);  /* previous call may change the stack */
287    }
288    ci = inc_ci(L);  /* now `enter' new function */
289    ci->func = func;
290    L->base = ci->base = base;
291    ci->top = L->base + p->maxstacksize;
292    lua_assert(ci->top <= L->stack_last);
293    L->savedpc = p->code;  /* starting point */
294    ci->tailcalls = 0;
295    ci->nresults = nresults;
296    for (st = L->top; st < ci->top; st++)
297      setnilvalue(st);
298    L->top = ci->top;
299    if (L->hookmask & LUA_MASKCALL) {
300      L->savedpc++;  /* hooks assume 'pc' is already incremented */
301      luaD_callhook(L, LUA_HOOKCALL, -1);
302      L->savedpc--;  /* correct 'pc' */
303    }
304    return PCRLUA;
305  }
306  else {  /* if is a C function, call it */
307    CallInfo *ci;
308    int n;
309    luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */
310    ci = inc_ci(L);  /* now `enter' new function */
311    ci->func = restorestack(L, funcr);
312    L->base = ci->base = ci->func + 1;
313    ci->top = L->top + LUA_MINSTACK;
314    lua_assert(ci->top <= L->stack_last);
315    ci->nresults = nresults;
316    if (L->hookmask & LUA_MASKCALL)
317      luaD_callhook(L, LUA_HOOKCALL, -1);
318    lua_unlock(L);
319    n = (*curr_func(L)->c.f)(L);  /* do the actual call */
320    lua_lock(L);
321    if (n < 0)  /* yielding? */
322      return PCRYIELD;
323    else {
324      luaD_poscall(L, L->top - n);
325      return PCRC;
326    }
327  }
328}
329
330
331static StkId callrethooks (lua_State *L, StkId firstResult) {
332  ptrdiff_t fr = savestack(L, firstResult);  /* next call may change stack */
333  luaD_callhook(L, LUA_HOOKRET, -1);
334  if (f_isLua(L->ci)) {  /* Lua function? */
335    while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */
336      luaD_callhook(L, LUA_HOOKTAILRET, -1);
337  }
338  return restorestack(L, fr);
339}
340
341
342int luaD_poscall (lua_State *L, StkId firstResult) {
343  StkId res;
344  int wanted, i;
345  CallInfo *ci;
346  if (L->hookmask & LUA_MASKRET)
347    firstResult = callrethooks(L, firstResult);
348  ci = L->ci--;
349  res = ci->func;  /* res == final position of 1st result */
350  wanted = ci->nresults;
351  L->base = (ci - 1)->base;  /* restore base */
352  L->savedpc = (ci - 1)->savedpc;  /* restore savedpc */
353  /* move results to correct place */
354  for (i = wanted; i != 0 && firstResult < L->top; i--)
355    setobjs2s(L, res++, firstResult++);
356  while (i-- > 0)
357    setnilvalue(res++);
358  L->top = res;
359  return (wanted - LUA_MULTRET);  /* 0 iff wanted == LUA_MULTRET */
360}
361
362
363/*
364** Call a function (C or Lua). The function to be called is at *func.
365** The arguments are on the stack, right after the function.
366** When returns, all the results are on the stack, starting at the original
367** function position.
368*/ 
369void luaD_call (lua_State *L, StkId func, int nResults) {
370  if (++L->nCcalls >= LUAI_MAXCCALLS) {
371    if (L->nCcalls == LUAI_MAXCCALLS)
372      luaG_runerror(L, "C stack overflow");
373    else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
374      luaD_throw(L, LUA_ERRERR);  /* error while handing stack error */
375  }
376  if (luaD_precall(L, func, nResults) == PCRLUA)  /* is a Lua function? */
377    luaV_execute(L, 1);  /* call it */
378  L->nCcalls--;
379  luaC_checkGC(L);
380}
381
382
383static void resume (lua_State *L, void *ud) {
384  StkId firstArg = cast(StkId, ud);
385  CallInfo *ci = L->ci;
386  if (L->status == 0) {  /* start coroutine? */
387    lua_assert(ci == L->base_ci && firstArg > L->base);
388    if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA)
389      return;
390  }
391  else {  /* resuming from previous yield */
392    lua_assert(L->status == LUA_YIELD);
393    L->status = 0;
394    if (!f_isLua(ci)) {  /* `common' yield? */
395      /* finish interrupted execution of `OP_CALL' */
396      lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL ||
397                 GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL);
398      if (luaD_poscall(L, firstArg))  /* complete it... */
399        L->top = L->ci->top;  /* and correct top if not multiple results */
400    }
401    else  /* yielded inside a hook: just continue its execution */
402      L->base = L->ci->base;
403  }
404  luaV_execute(L, cast_int(L->ci - L->base_ci));
405}
406
407
408static int resume_error (lua_State *L, const char *msg) {
409  L->top = L->ci->base;
410  setsvalue2s(L, L->top, luaS_new(L, msg));
411  incr_top(L);
412  lua_unlock(L);
413  return LUA_ERRRUN;
414}
415
416
417LUA_API int lua_resume (lua_State *L, int nargs) {
418  int status;
419  lua_lock(L);
420  if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci))
421      return resume_error(L, "cannot resume non-suspended coroutine");
422  if (L->nCcalls >= LUAI_MAXCCALLS)
423    return resume_error(L, "C stack overflow");
424  luai_userstateresume(L, nargs);
425  lua_assert(L->errfunc == 0);
426  L->baseCcalls = ++L->nCcalls;
427  status = luaD_rawrunprotected(L, resume, L->top - nargs);
428  if (status != 0) {  /* error? */
429    L->status = cast_byte(status);  /* mark thread as `dead' */
430    luaD_seterrorobj(L, status, L->top);
431    L->ci->top = L->top;
432  }
433  else {
434    lua_assert(L->nCcalls == L->baseCcalls);
435    status = L->status;
436  }
437  --L->nCcalls;
438  lua_unlock(L);
439  return status;
440}
441
442
443LUA_API int lua_yield (lua_State *L, int nresults) {
444  luai_userstateyield(L, nresults);
445  lua_lock(L);
446  if (L->nCcalls > L->baseCcalls)
447    luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");
448  L->base = L->top - nresults;  /* protect stack slots below */
449  L->status = LUA_YIELD;
450  lua_unlock(L);
451  return -1;
452}
453
454
455int luaD_pcall (lua_State *L, Pfunc func, void *u,
456                ptrdiff_t old_top, ptrdiff_t ef) {
457  int status;
458  unsigned short oldnCcalls = L->nCcalls;
459  ptrdiff_t old_ci = saveci(L, L->ci);
460  lu_byte old_allowhooks = L->allowhook;
461  ptrdiff_t old_errfunc = L->errfunc;
462  L->errfunc = ef;
463  status = luaD_rawrunprotected(L, func, u);
464  if (status != 0) {  /* an error occurred? */
465    StkId oldtop = restorestack(L, old_top);
466    luaF_close(L, oldtop);  /* close eventual pending closures */
467    luaD_seterrorobj(L, status, oldtop);
468    L->nCcalls = oldnCcalls;
469    L->ci = restoreci(L, old_ci);
470    L->base = L->ci->base;
471    L->savedpc = L->ci->savedpc;
472    L->allowhook = old_allowhooks;
473    restore_stack_limit(L);
474  }
475  L->errfunc = old_errfunc;
476  return status;
477}
478
479
480
481/*
482** Execute a protected parser.
483*/
484struct SParser {  /* data to `f_parser' */
485  ZIO *z;
486  Mbuffer buff;  /* buffer to be used by the scanner */
487  const char *name;
488};
489
490static void f_parser (lua_State *L, void *ud) {
491  int i;
492  Proto *tf;
493  Closure *cl;
494  struct SParser *p = cast(struct SParser *, ud);
495  int c = luaZ_lookahead(p->z);
496  luaC_checkGC(L);
497  tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z,
498                                                             &p->buff, p->name);
499  cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));
500  cl->l.p = tf;
501  for (i = 0; i < tf->nups; i++)  /* initialize eventual upvalues */
502    cl->l.upvals[i] = luaF_newupval(L);
503  setclvalue(L, L->top, cl);
504  incr_top(L);
505}
506
507
508int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) {
509  struct SParser p;
510  int status;
511  p.z = z; p.name = name;
512  luaZ_initbuffer(L, &p.buff);
513  status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);
514  luaZ_freebuffer(L, &p.buff);
515  return status;
516}
517
518
Note: See TracBrowser for help on using the repository browser.