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