Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ceguilua/src/lua/ldo.c @ 2144

Last change on this file since 2144 was 1806, checked in by rgrieder, 16 years ago

added single 5.1.3 directory for lua since CEGUILua 0.5 can also build against lua 5.1

  • Property svn:eol-style set to native
File size: 14.5 KB
RevLine 
[1806]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.