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