summaryrefslogtreecommitdiff
path: root/lbaselib.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2014-05-16 15:54:01 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2014-05-16 15:54:01 -0300
commite2be310a85df0b8eb5c406aa0397088a66b98c47 (patch)
tree350f6dd4911c9b9011e5e03a04d02b8c2056b8c4 /lbaselib.c
parent17159b491c98e7da79b413d8b0ca770a1af116f3 (diff)
downloadlua-e2be310a85df0b8eb5c406aa0397088a66b98c47.tar.gz
lua-e2be310a85df0b8eb5c406aa0397088a66b98c47.tar.bz2
lua-e2be310a85df0b8eb5c406aa0397088a66b98c47.zip
better(?) implementation for 'pcall'/'xpcall' (regarding the insertion
of the boolean first result)
Diffstat (limited to 'lbaselib.c')
-rw-r--r--lbaselib.c55
1 files changed, 35 insertions, 20 deletions
diff --git a/lbaselib.c b/lbaselib.c
index 5b22a1fc..190f0009 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lbaselib.c,v 1.285 2014/03/12 20:57:40 roberto Exp roberto $ 2** $Id: lbaselib.c,v 1.286 2014/05/01 18:18:06 roberto Exp roberto $
3** Basic library 3** Basic library
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -379,44 +379,59 @@ static int luaB_select (lua_State *L) {
379} 379}
380 380
381 381
382static int finishpcall (lua_State *L, int status) { 382/*
383 if (!lua_checkstack(L, 1)) { /* no space for extra boolean? */ 383** Finishes a 'pcall' or 'xpcall'. Both functions already pushed a
384 lua_settop(L, 0); /* create space for return values */ 384** 'true' before doing the call, so in case of sucess 'finishpcall'
385 lua_pushboolean(L, 0); 385** only has to return everything in the stack minus 'extra' values
386 lua_pushstring(L, "stack overflow"); 386** (where 'extra' is exactly the number of items to be ignored).
387*/
388static int finishpcall (lua_State *L, int ok, int extra) {
389 if (!ok) { /* error? */
390 lua_pushboolean(L, 0); /* first result (false) */
391 lua_pushvalue(L, -2); /* error message */
387 return 2; /* return false, msg */ 392 return 2; /* return false, msg */
388 } 393 }
389 lua_pushboolean(L, status); /* first result (status) */ 394 else
390 lua_replace(L, 1); /* put first result in first slot */ 395 return lua_gettop(L) - extra; /* return all results */
391 return lua_gettop(L);
392} 396}
393 397
394 398
399/*
400** Continuation function for 'pcall' and 'xpcall': get appropriate
401** state through 'lua_getctx' and call 'finishpcall' to finish the
402** original function.
403*/
395static int pcallcont (lua_State *L) { 404static int pcallcont (lua_State *L) {
396 int status = lua_getctx(L, NULL); 405 int extra;
397 return finishpcall(L, (status == LUA_YIELD)); 406 int status = lua_getctx(L, &extra);
407 return finishpcall(L, (status == LUA_YIELD), extra);
398} 408}
399 409
400 410
401static int luaB_pcall (lua_State *L) { 411static int luaB_pcall (lua_State *L) {
402 int status; 412 int status;
403 luaL_checkany(L, 1); 413 luaL_checkany(L, 1);
404 lua_pushnil(L); 414 lua_pushboolean(L, 1); /* first result if no errors */
405 lua_insert(L, 1); /* create space for status result */ 415 lua_insert(L, 1); /* put it in place */
406 status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, pcallcont); 416 status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, pcallcont);
407 return finishpcall(L, (status == LUA_OK)); 417 return finishpcall(L, (status == LUA_OK), 0);
408} 418}
409 419
410 420
421/*
422** Do a protected call with error handling. After 'lua_rotate', the
423** stack will have <f, err, true, f, [args...]>; so, the function passes
424** 2 to 'finishpcall' to skip the 2 first values when returning results.
425*/
411static int luaB_xpcall (lua_State *L) { 426static int luaB_xpcall (lua_State *L) {
412 int status; 427 int status;
413 int n = lua_gettop(L); 428 int n = lua_gettop(L);
414 luaL_argcheck(L, n >= 2, 2, "value expected"); 429 luaL_checktype(L, 2, LUA_TFUNCTION); /* check error function */
415 lua_pushvalue(L, 1); /* exchange function... */ 430 lua_pushboolean(L, 1); /* first result */
416 lua_copy(L, 2, 1); /* ...and error handler */ 431 lua_pushvalue(L, 1); /* function */
417 lua_replace(L, 2); 432 lua_rotate(L, 3, 2); /* move them below function's arguments */
418 status = lua_pcallk(L, n - 2, LUA_MULTRET, 1, 0, pcallcont); 433 status = lua_pcallk(L, n - 2, LUA_MULTRET, 2, 2, pcallcont);
419 return finishpcall(L, (status == LUA_OK)); 434 return finishpcall(L, (status == LUA_OK), 2);
420} 435}
421 436
422 437