ldo.c

Go to the documentation of this file.
00001 /*
00002 ** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $
00003 ** Stack and Call structure of Lua
00004 ** See Copyright Notice in lua.h
00005 */
00006 
00007 
00008 #include <setjmp.h>
00009 #include <stdlib.h>
00010 #include <string.h>
00011 
00012 #define ldo_c
00013 #define LUA_CORE
00014 
00015 #include "lua.h"
00016 
00017 #include "ldebug.h"
00018 #include "ldo.h"
00019 #include "lfunc.h"
00020 #include "lgc.h"
00021 #include "lmem.h"
00022 #include "lobject.h"
00023 #include "lopcodes.h"
00024 #include "lparser.h"
00025 #include "lstate.h"
00026 #include "lstring.h"
00027 #include "ltable.h"
00028 #include "ltm.h"
00029 #include "lundump.h"
00030 #include "lvm.h"
00031 #include "lzio.h"
00032 
00033 
00034 #ifdef LUA_SYMBIAN
00035 #include <e32std.h>
00036 #endif
00037 
00038 
00039 /*
00040 ** {======================================================
00041 ** Error-recovery functions
00042 ** =======================================================
00043 */
00044 
00045 
00046 /* chain list of long jump buffers */
00047 struct lua_longjmp {
00048   struct lua_longjmp *previous;
00049   luai_jmpbuf b;
00050   volatile int status;  /* error code */
00051 };
00052 
00053 
00054 void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {
00055   switch (errcode) {
00056     case LUA_ERRMEM: {
00057       setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG));
00058       break;
00059     }
00060     case LUA_ERRERR: {
00061       setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
00062       break;
00063     }
00064     case LUA_ERRSYNTAX:
00065     case LUA_ERRRUN: {
00066       setobjs2s(L, oldtop, L->top - 1);  /* error message on current top */
00067       break;
00068     }
00069   }
00070   L->top = oldtop + 1;
00071 }
00072 
00073 
00074 static void restore_stack_limit (lua_State *L) {
00075   lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);
00076   if (L->size_ci > LUAI_MAXCALLS) {  /* there was an overflow? */
00077     int inuse = cast_int(L->ci - L->base_ci);
00078     if (inuse + 1 < LUAI_MAXCALLS)  /* can `undo' overflow? */
00079       luaD_reallocCI(L, LUAI_MAXCALLS);
00080   }
00081 }
00082 
00083 
00084 static void resetstack (lua_State *L, int status) {
00085   L->ci = L->base_ci;
00086   L->base = L->ci->base;
00087   luaF_close(L, L->base);  /* close eventual pending closures */
00088   luaD_seterrorobj(L, status, L->base);
00089   L->nCcalls = L->baseCcalls;
00090   L->allowhook = 1;
00091   restore_stack_limit(L);
00092   L->errfunc = 0;
00093   L->errorJmp = NULL;
00094 }
00095 
00096 
00097 void luaD_throw (lua_State *L, int errcode) {
00098   //logg("luaD_throw errCode %d", errcode);
00099   if (L->errorJmp) {
00100     //logt("have errorJmp");
00101     L->errorJmp->status = errcode;
00102     LUAI_THROW(L, L->errorJmp);
00103   }
00104   else {
00105     L->status = cast_byte(errcode);
00106     if (G(L)->panic) {
00107       resetstack(L, errcode);
00108       lua_unlock(L);
00109       G(L)->panic(L);
00110     }
00111     exit(EXIT_FAILURE);
00112   }
00113 }
00114 
00115 
00116 int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
00117   struct lua_longjmp lj;
00118   lj.status = 0;
00119   lj.previous = L->errorJmp;  /* chain new error handler */
00120   L->errorJmp = &lj;
00121   LUAI_TRY(L, &lj,
00122     (*f)(L, ud);
00123   );
00124   //logt("exited LUAI_TRY");
00125   L->errorJmp = lj.previous;  /* restore old error handler */
00126   return lj.status;
00127 }
00128 
00129 /* }====================================================== */
00130 
00131 
00132 static void correctstack (lua_State *L, TValue *oldstack) {
00133   CallInfo *ci;
00134   GCObject *up;
00135   L->top = (L->top - oldstack) + L->stack;
00136   for (up = L->openupval; up != NULL; up = up->gch.next)
00137     gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;
00138   for (ci = L->base_ci; ci <= L->ci; ci++) {
00139     ci->top = (ci->top - oldstack) + L->stack;
00140     ci->base = (ci->base - oldstack) + L->stack;
00141     ci->func = (ci->func - oldstack) + L->stack;
00142   }
00143   L->base = (L->base - oldstack) + L->stack;
00144 }
00145 
00146 
00147 void luaD_reallocstack (lua_State *L, int newsize) {
00148   TValue *oldstack = L->stack;
00149   int realsize = newsize + 1 + EXTRA_STACK;
00150   lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);
00151   luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue);
00152   L->stacksize = realsize;
00153   L->stack_last = L->stack+newsize;
00154   correctstack(L, oldstack);
00155 }
00156 
00157 
00158 void luaD_reallocCI (lua_State *L, int newsize) {
00159   CallInfo *oldci = L->base_ci;
00160   luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);
00161   L->size_ci = newsize;
00162   L->ci = (L->ci - oldci) + L->base_ci;
00163   L->end_ci = L->base_ci + L->size_ci - 1;
00164 }
00165 
00166 
00167 void luaD_growstack (lua_State *L, int n) {
00168   if (n <= L->stacksize)  /* double size is enough? */
00169     luaD_reallocstack(L, 2*L->stacksize);
00170   else
00171     luaD_reallocstack(L, L->stacksize + n);
00172 }
00173 
00174 
00175 static CallInfo *growCI (lua_State *L) {
00176   if (L->size_ci > LUAI_MAXCALLS)  /* overflow while handling overflow? */
00177     luaD_throw(L, LUA_ERRERR);
00178   else {
00179     luaD_reallocCI(L, 2*L->size_ci);
00180     if (L->size_ci > LUAI_MAXCALLS)
00181       luaG_runerror_1(L, "stack overflow");
00182   }
00183   return ++L->ci;
00184 }
00185 
00186 
00187 void luaD_callhook (lua_State *L, int event, int line) {
00188   lua_Hook hook = L->hook;
00189   if (hook && L->allowhook) {
00190     ptrdiff_t top = savestack(L, L->top);
00191     ptrdiff_t ci_top = savestack(L, L->ci->top);
00192     lua_Debug ar;
00193     ar.event = event;
00194     ar.currentline = line;
00195     if (event == LUA_HOOKTAILRET)
00196       ar.i_ci = 0;  /* tail call; no debug information about it */
00197     else
00198       ar.i_ci = cast_int(L->ci - L->base_ci);
00199     luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */
00200     L->ci->top = L->top + LUA_MINSTACK;
00201     lua_assert(L->ci->top <= L->stack_last);
00202     L->allowhook = 0;  /* cannot call hooks inside a hook */
00203     lua_unlock(L);
00204     (*hook)(L, &ar);
00205     lua_lock(L);
00206     lua_assert(!L->allowhook);
00207     L->allowhook = 1;
00208     L->ci->top = restorestack(L, ci_top);
00209     L->top = restorestack(L, top);
00210   }
00211 }
00212 
00213 
00214 static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
00215   int i;
00216   int nfixargs = p->numparams;
00217   Table *htab = NULL;
00218   StkId base, fixed;
00219   for (; actual < nfixargs; ++actual)
00220     setnilvalue(L->top++);
00221 #if defined(LUA_COMPAT_VARARG)
00222   if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */
00223     int nvar = actual - nfixargs;  /* number of extra arguments */
00224     lua_assert(p->is_vararg & VARARG_HASARG);
00225     luaC_checkGC(L);
00226     htab = luaH_new(L, nvar, 1);  /* create `arg' table */
00227     for (i=0; i<nvar; i++)  /* put extra arguments into `arg' table */
00228       setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);
00229     /* store counter in field `n' */
00230     setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
00231   }
00232 #endif
00233   /* move fixed parameters to final position */
00234   fixed = L->top - actual;  /* first fixed argument */
00235   base = L->top;  /* final position of first argument */
00236   for (i=0; i<nfixargs; i++) {
00237     setobjs2s(L, L->top++, fixed+i);
00238     setnilvalue(fixed+i);
00239   }
00240   /* add `arg' parameter */
00241   if (htab) {
00242     sethvalue(L, L->top++, htab);
00243     lua_assert(iswhite(obj2gco(htab)));
00244   }
00245   return base;
00246 }
00247 
00248 
00249 static StkId tryfuncTM (lua_State *L, StkId func) {
00250   const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL);
00251   StkId p;
00252   ptrdiff_t funcr = savestack(L, func);
00253   if (!ttisfunction(tm))
00254     luaG_typeerror(L, func, "call");
00255   /* Open a hole inside the stack at `func' */
00256   for (p = L->top; p > func; p--) setobjs2s(L, p, p-1);
00257   incr_top(L);
00258   func = restorestack(L, funcr);  /* previous call may change stack */
00259   setobj2s(L, func, tm);  /* tag method is the new function to be called */
00260   return func;
00261 }
00262 
00263 
00264 
00265 #define inc_ci(L) \
00266   ((L->ci == L->end_ci) ? growCI(L) : \
00267    (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci))
00268 
00269 
00270 int luaD_precall (lua_State *L, StkId func, int nresults) {
00271   LClosure *cl;
00272   ptrdiff_t funcr;
00273   if (!ttisfunction(func)) /* `func' is not a function? */
00274     func = tryfuncTM(L, func);  /* check the `function' tag method */
00275   funcr = savestack(L, func);
00276   cl = &clvalue(func)->l;
00277   L->ci->savedpc = L->savedpc;
00278   if (!cl->isC) {  /* Lua function? prepare its call */
00279     CallInfo *ci;
00280     StkId st, base;
00281     Proto *p = cl->p;
00282     luaD_checkstack(L, p->maxstacksize);
00283     func = restorestack(L, funcr);
00284     if (!p->is_vararg) {  /* no varargs? */
00285       base = func + 1;
00286       if (L->top > base + p->numparams)
00287         L->top = base + p->numparams;
00288     }
00289     else {  /* vararg function */
00290       int nargs = cast_int(L->top - func) - 1;
00291       base = adjust_varargs(L, p, nargs);
00292       func = restorestack(L, funcr);  /* previous call may change the stack */
00293     }
00294     ci = inc_ci(L);  /* now `enter' new function */
00295     ci->func = func;
00296     L->base = ci->base = base;
00297     ci->top = L->base + p->maxstacksize;
00298     lua_assert(ci->top <= L->stack_last);
00299     L->savedpc = p->code;  /* starting point */
00300     ci->tailcalls = 0;
00301     ci->nresults = nresults;
00302     for (st = L->top; st < ci->top; st++)
00303       setnilvalue(st);
00304     L->top = ci->top;
00305     if (L->hookmask & LUA_MASKCALL) {
00306       L->savedpc++;  /* hooks assume 'pc' is already incremented */
00307       luaD_callhook(L, LUA_HOOKCALL, -1);
00308       L->savedpc--;  /* correct 'pc' */
00309     }
00310     return PCRLUA;
00311   }
00312   else {  /* if is a C function, call it */
00313     CallInfo *ci;
00314     int n;
00315     luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */
00316     ci = inc_ci(L);  /* now `enter' new function */
00317     ci->func = restorestack(L, funcr);
00318     L->base = ci->base = ci->func + 1;
00319     ci->top = L->top + LUA_MINSTACK;
00320     lua_assert(ci->top <= L->stack_last);
00321     ci->nresults = nresults;
00322     if (L->hookmask & LUA_MASKCALL)
00323       luaD_callhook(L, LUA_HOOKCALL, -1);
00324     lua_unlock(L);
00325     n = (*curr_func(L)->c.f)(L);  /* do the actual call */
00326     lua_lock(L);
00327     if (n < 0)  /* yielding? */
00328       return PCRYIELD;
00329     else {
00330       luaD_poscall(L, L->top - n);
00331       return PCRC;
00332     }
00333   }
00334 }
00335 
00336 
00337 static StkId callrethooks (lua_State *L, StkId firstResult) {
00338   ptrdiff_t fr = savestack(L, firstResult);  /* next call may change stack */
00339   luaD_callhook(L, LUA_HOOKRET, -1);
00340   if (f_isLua(L->ci)) {  /* Lua function? */
00341     while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */
00342       luaD_callhook(L, LUA_HOOKTAILRET, -1);
00343   }
00344   return restorestack(L, fr);
00345 }
00346 
00347 
00348 int luaD_poscall (lua_State *L, StkId firstResult) {
00349   StkId res;
00350   int wanted, i;
00351   CallInfo *ci;
00352   if (L->hookmask & LUA_MASKRET)
00353     firstResult = callrethooks(L, firstResult);
00354   ci = L->ci--;
00355   res = ci->func;  /* res == final position of 1st result */
00356   wanted = ci->nresults;
00357   L->base = (ci - 1)->base;  /* restore base */
00358   L->savedpc = (ci - 1)->savedpc;  /* restore savedpc */
00359   /* move results to correct place */
00360   for (i = wanted; i != 0 && firstResult < L->top; i--)
00361     setobjs2s(L, res++, firstResult++);
00362   while (i-- > 0)
00363     setnilvalue(res++);
00364   L->top = res;
00365   return (wanted - LUA_MULTRET);  /* 0 iff wanted == LUA_MULTRET */
00366 }
00367 
00368 
00369 /*
00370 ** Call a function (C or Lua). The function to be called is at *func.
00371 ** The arguments are on the stack, right after the function.
00372 ** When returns, all the results are on the stack, starting at the original
00373 ** function position.
00374 */ 
00375 void luaD_call (lua_State *L, StkId func, int nResults) {
00376   if (++L->nCcalls >= LUAI_MAXCCALLS) {
00377     if (L->nCcalls == LUAI_MAXCCALLS)
00378       luaG_runerror_1(L, "C stack overflow");
00379     else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
00380       luaD_throw(L, LUA_ERRERR);  /* error while handing stack error */
00381   }
00382   if (luaD_precall(L, func, nResults) == PCRLUA)  /* is a Lua function? */
00383     luaV_execute(L, 1);  /* call it */
00384   L->nCcalls--;
00385   luaC_checkGC(L);
00386 }
00387 
00388 
00389 static void resume (lua_State *L, void *ud) {
00390   StkId firstArg = cast(StkId, ud);
00391   CallInfo *ci = L->ci;
00392   if (L->status == 0) {  /* start coroutine? */
00393     lua_assert(ci == L->base_ci && firstArg > L->base);
00394     if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA)
00395       return;
00396   }
00397   else {  /* resuming from previous yield */
00398     lua_assert(L->status == LUA_YIELD);
00399     L->status = 0;
00400     if (!f_isLua(ci)) {  /* `common' yield? */
00401       /* finish interrupted execution of `OP_CALL' */
00402       lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL ||
00403                  GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL);
00404       if (luaD_poscall(L, firstArg))  /* complete it... */
00405         L->top = L->ci->top;  /* and correct top if not multiple results */
00406     }
00407     else  /* yielded inside a hook: just continue its execution */
00408       L->base = L->ci->base;
00409   }
00410   luaV_execute(L, cast_int(L->ci - L->base_ci));
00411 }
00412 
00413 
00414 static int resume_error (lua_State *L, const char *msg) {
00415   L->top = L->ci->base;
00416   setsvalue2s(L, L->top, luaS_new(L, msg));
00417   incr_top(L);
00418   lua_unlock(L);
00419   return LUA_ERRRUN;
00420 }
00421 
00422 
00423 LUA_API int lua_resume (lua_State *L, int nargs) {
00424   int status;
00425   lua_lock(L);
00426   if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci))
00427       return resume_error(L, "cannot resume non-suspended coroutine");
00428   if (L->nCcalls >= LUAI_MAXCCALLS)
00429     return resume_error(L, "C stack overflow");
00430   luai_userstateresume(L, nargs);
00431   lua_assert(L->errfunc == 0);
00432   L->baseCcalls = ++L->nCcalls;
00433   status = luaD_rawrunprotected(L, resume, L->top - nargs);
00434   if (status != 0) {  /* error? */
00435     L->status = cast_byte(status);  /* mark thread as `dead' */
00436     luaD_seterrorobj(L, status, L->top);
00437     L->ci->top = L->top;
00438   }
00439   else {
00440     lua_assert(L->nCcalls == L->baseCcalls);
00441     status = L->status;
00442   }
00443   --L->nCcalls;
00444   lua_unlock(L);
00445   return status;
00446 }
00447 
00448 
00449 LUA_API int lua_yield (lua_State *L, int nresults) {
00450   luai_userstateyield(L, nresults);
00451   lua_lock(L);
00452   if (L->nCcalls > L->baseCcalls)
00453     luaG_runerror_1(L, "attempt to yield across metamethod/C-call boundary");
00454   L->base = L->top - nresults;  /* protect stack slots below */
00455   L->status = LUA_YIELD;
00456   lua_unlock(L);
00457   return -1;
00458 }
00459 
00460 
00461 int luaD_pcall (lua_State *L, Pfunc func, void *u,
00462                 ptrdiff_t old_top, ptrdiff_t ef) {
00463   int status;
00464   unsigned short oldnCcalls = L->nCcalls;
00465   ptrdiff_t old_ci = saveci(L, L->ci);
00466   lu_byte old_allowhooks = L->allowhook;
00467   ptrdiff_t old_errfunc = L->errfunc;
00468   L->errfunc = ef;
00469   status = luaD_rawrunprotected(L, func, u);
00470   if (status != 0) {  /* an error occurred? */
00471     StkId oldtop = restorestack(L, old_top);
00472     luaF_close(L, oldtop);  /* close eventual pending closures */
00473     luaD_seterrorobj(L, status, oldtop);
00474     L->nCcalls = oldnCcalls;
00475     L->ci = restoreci(L, old_ci);
00476     L->base = L->ci->base;
00477     L->savedpc = L->ci->savedpc;
00478     L->allowhook = old_allowhooks;
00479     restore_stack_limit(L);
00480   }
00481   L->errfunc = old_errfunc;
00482   return status;
00483 }
00484 
00485 
00486 
00487 /*
00488 ** Execute a protected parser.
00489 */
00490 struct SParser {  /* data to `f_parser' */
00491   ZIO *z;
00492   Mbuffer buff;  /* buffer to be used by the scanner */
00493   const char *name;
00494 };
00495 
00496 static void f_parser (lua_State *L, void *ud) {
00497   int i;
00498   Proto *tf;
00499   Closure *cl;
00500   struct SParser *p = cast(struct SParser *, ud);
00501   int c = luaZ_lookahead(p->z);
00502   luaC_checkGC(L);
00503   tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z,
00504                                                              &p->buff, p->name);
00505   cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));
00506   cl->l.p = tf;
00507   for (i = 0; i < tf->nups; i++)  /* initialize eventual upvalues */
00508     cl->l.upvals[i] = luaF_newupval(L);
00509   setclvalue(L, L->top, cl);
00510   incr_top(L);
00511 }
00512 
00513 
00514 int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) {
00515   struct SParser p;
00516   int status;
00517   p.z = z; p.name = name;
00518   luaZ_initbuffer(L, &p.buff);
00519   status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);
00520   luaZ_freebuffer(L, &p.buff);
00521   return status;
00522 }
00523 
00524 

ContextLogger2—ContextLogger2 Logger Daemon Internals—Generated on Mon May 2 13:49:54 2011 by Doxygen 1.6.1