Fix arg check and behavior of xpcall() to leave stack intact.
This commit is contained in:
11
README.html
11
README.html
@@ -17,7 +17,7 @@
|
||||
Getting Started with LuaJ
|
||||
|
||||
</h1>
|
||||
James Roseborough, Ian Farmer, Version 1.0
|
||||
James Roseborough, Ian Farmer, Version 1.0.1
|
||||
<p>
|
||||
<small>
|
||||
Copyright © 2007-2009 Luaj.org.
|
||||
@@ -36,6 +36,8 @@ Freely available under the terms of the
|
||||
<a href="#4">building</a>
|
||||
·
|
||||
<a href="#5">downloads</a>
|
||||
·
|
||||
<a href="#6">release notes</a>
|
||||
|
||||
<!-- ====================================================================== -->
|
||||
<p>
|
||||
@@ -334,3 +336,10 @@ and LuaForge:
|
||||
<a href="http://luaforge.net/frs/?group_id=457">LuaForge Luaj Project Area</a>
|
||||
</pre>
|
||||
|
||||
<h1>6 - <a name="6">Release Notes</a></h1>
|
||||
|
||||
Main changes by version:
|
||||
<table cellspacing="10"><tr><td><table cellspacing="4">
|
||||
<tr><td> <b>1.0</b></td><td>Initial publicly supported release.</td></tr>
|
||||
<tr><td> <b>1.0.1</b></td><td>Fix arg check and behavior of xpcall() to leave stack intact.</td></tr>
|
||||
</table></td></tr></table>
|
||||
|
||||
@@ -198,7 +198,7 @@ public class BaseLib extends LFunction {
|
||||
case PCALL: {
|
||||
vm.checkany(1);
|
||||
int n = vm.gettop();
|
||||
int s = vm.pcall( n-1, Lua.LUA_MULTRET, 0 );
|
||||
int s = vm.pcall( n-1, Lua.LUA_MULTRET );
|
||||
if ( s == 0 ) { // success, results are on stack
|
||||
vm.pushboolean( true );
|
||||
vm.insert( 1 );
|
||||
@@ -210,26 +210,17 @@ public class BaseLib extends LFunction {
|
||||
}
|
||||
}
|
||||
case XPCALL: {
|
||||
LValue errfun = vm.checkany(3);
|
||||
LValue errfun = vm.checkany(2);
|
||||
vm.settop(1);
|
||||
int s = vm.pcall( 0, Lua.LUA_MULTRET, 0 );
|
||||
int s = vm.xpcall( 0, Lua.LUA_MULTRET, errfun );
|
||||
if ( s == 0 ) { // success, results are on stack
|
||||
vm.pushboolean( true );
|
||||
vm.insert( 1 );
|
||||
return -1;
|
||||
} else { // error, error message is on the stack
|
||||
vm.pushlvalue( errfun );
|
||||
vm.pushboolean( false );
|
||||
vm.insert( 1 );
|
||||
s = vm.pcall( vm.gettop()-1, 1, 0 );
|
||||
if ( s == 0 ) {
|
||||
vm.pushboolean( false );
|
||||
vm.insert( 1 );
|
||||
return -1;
|
||||
} else { // error in error handler
|
||||
vm.pushboolean(false);
|
||||
vm.pushstring("error in error handling");
|
||||
return 2;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
case ERROR: {
|
||||
@@ -489,7 +480,7 @@ public class BaseLib extends LFunction {
|
||||
try {
|
||||
while ( true ) {
|
||||
setResult(vm,c);
|
||||
if ( 0 != vm.pcall(0, 1, 0) ) {
|
||||
if ( 0 != vm.pcall(0, 1) ) {
|
||||
setErrorResult(vm, vm.tostring(2));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -74,14 +74,18 @@ public class LuaErrorException extends RuntimeException {
|
||||
* @return
|
||||
*/
|
||||
private static String addLineInfo(LuaState vm, String message, int level) {
|
||||
if ( level == 0 || message == null )
|
||||
return message;
|
||||
// add position information
|
||||
if ( vm == null ) {
|
||||
if ( LThread.running != null )
|
||||
vm = LThread.running.vm;
|
||||
else
|
||||
vm = LuaState.mainState;
|
||||
if ( vm == null )
|
||||
return message;
|
||||
}
|
||||
return vm != null? vm.getFileLine(level) + ": " + message: message;
|
||||
if ( level > 0 ) {
|
||||
message = vm.getFileLine(level);
|
||||
}
|
||||
return vm.luaV_call_errfunc( message );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ public class LuaState extends Lua {
|
||||
public int cc = -1;
|
||||
public CallInfo[] calls = new CallInfo[LUA_MINCALLS];
|
||||
protected Stack upvals = new Stack();
|
||||
protected LFunction panic;
|
||||
protected LValue errfunc;
|
||||
|
||||
static LuaState mainState;
|
||||
public LTable _G;
|
||||
@@ -362,24 +362,6 @@ public class LuaState extends Lua {
|
||||
* <a href="#lua_pcall"><code>lua_pcall</code></a> always removes the
|
||||
* function and its arguments from the stack.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* If <code>errfunc</code> is 0, then the error message returned on the
|
||||
* stack is exactly the original error message. Otherwise,
|
||||
* <code>errfunc</code> is the stack index of an
|
||||
* <em>error handler function</em>. (In the current implementation, this
|
||||
* index cannot be a pseudo-index.) In case of runtime errors, this function
|
||||
* will be called with the error message and its return value will be the
|
||||
* message returned on the stack by <a href="#lua_pcall"><code>lua_pcall</code></a>.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Typically, the error handler function is used to add more debug
|
||||
* information to the error message, such as a stack traceback. Such
|
||||
* information cannot be gathered after the return of <a href="#lua_pcall"><code>lua_pcall</code></a>,
|
||||
* since by then the stack has unwound.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* The <a href="#lua_pcall"><code>lua_pcall</code></a> function returns
|
||||
* 0 in case of success or one of the following error codes (defined in
|
||||
@@ -399,7 +381,7 @@ public class LuaState extends Lua {
|
||||
*
|
||||
* </ul>
|
||||
*/
|
||||
public int pcall( int nargs, int nreturns, int errfunc ) {
|
||||
public int pcall( int nargs, int nreturns ) {
|
||||
// save stack state
|
||||
int oldtop = top;
|
||||
int oldbase = base;
|
||||
@@ -446,6 +428,46 @@ public class LuaState extends Lua {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calls a function in protected mode with an error function.
|
||||
* <span class="apii">[-(nargs + 1), +(nresults|1), <em>-</em>]</span>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Both <code>nargs</code> and <code>nresults</code> have the same
|
||||
* meaning as in <a href="#lua_call"><code>lua_call</code></a>. If there
|
||||
* are no errors during the call, <a href="#lua_xpcall"><code>lua_xpcall</code></a>
|
||||
* behaves exactly like <a href="#lua_call"><code>lua_call</code></a>.
|
||||
* However, if there is any error, <a href="#lua_xpcall"><code>lua_xpcall</code></a>
|
||||
* catches it, pushes a single value on the stack (the error message), and
|
||||
* tries to call the supplied error function.
|
||||
*
|
||||
* <p>In case of runtime errors, this function
|
||||
* will be called with the error message and its return value will be the
|
||||
* message returned on the stack by <a href="#lua_pcall"><code>lua_pcall</code></a>.
|
||||
*
|
||||
* <p>
|
||||
* Typically, the error handler function is used to add more debug
|
||||
* information to the error message, such as a stack traceback. Such
|
||||
* information cannot be gathered after the return of <a href="#lua_pcall"><code>lua_pcall</code></a>,
|
||||
* since by then the stack has unwound.
|
||||
*
|
||||
* <p>
|
||||
* The return values for
|
||||
* <a href="#lua_xpcall"><code>lua_xpcall</code></a> are the same as those for
|
||||
* <a href="#lua_pcall"><code>lua_pcall</code></a>
|
||||
*/
|
||||
public int xpcall( int nargs, int nreturns, LValue errfunc ) {
|
||||
LValue preverrfunc = this.errfunc;
|
||||
try {
|
||||
this.errfunc = errfunc;
|
||||
return pcall( nargs, nreturns );
|
||||
} finally {
|
||||
this.errfunc = preverrfunc;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a Lua chunk. <span class="apii">[-0, +1, <em>-</em>]</span>
|
||||
*
|
||||
@@ -2361,6 +2383,40 @@ public class LuaState extends Lua {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call the error function, if any, to possibly modify the message
|
||||
*/
|
||||
public String luaV_call_errfunc(String message) {
|
||||
|
||||
// error function is run at most once
|
||||
if ( errfunc == null )
|
||||
return message;
|
||||
|
||||
// run the error function
|
||||
int oldtop = top;
|
||||
int oldmask = hookmask;
|
||||
LValue olderr = errfunc;
|
||||
try {
|
||||
hookmask = 0;
|
||||
errfunc = null;
|
||||
if ( cc >= 0 )
|
||||
top = base + this.calls[cc].closure.p.maxstacksize;
|
||||
pushlvalue(olderr);
|
||||
pushstring(message);
|
||||
call(1,1);
|
||||
return poplvalue().toJavaString();
|
||||
|
||||
} catch ( Throwable t ) {
|
||||
return "error in error handling: "+t.getMessage();
|
||||
|
||||
} finally {
|
||||
top = oldtop;
|
||||
hookmask = oldmask;
|
||||
errfunc = olderr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// Debug hooks.
|
||||
|
||||
@@ -159,7 +159,7 @@ public class lua {
|
||||
// load via "require"
|
||||
vm.getglobal("require");
|
||||
vm.pushstring(libname);
|
||||
int status = vm.pcall(1, 0, 0);
|
||||
int status = vm.pcall(1, 0);
|
||||
if ( status == 0 )
|
||||
return;
|
||||
|
||||
|
||||
@@ -58,3 +58,18 @@ for i = 0,4 do
|
||||
print( 'pcall(ge,i)', i, pcall(ge,i) )
|
||||
end
|
||||
|
||||
-- xpcall tests
|
||||
local function goodfunction() return 'from good function' end
|
||||
local function badfunction() error( 'from bad function') end
|
||||
local function goodhandler(msg) return '-->'..msg..'<--' end
|
||||
local function badhandler(msg) error( 'from bad handler' ) end
|
||||
print( 'xpcall(error,goodhandler)', ( xpcall(error,goodhandler) ) )
|
||||
print( 'xpcall(goodfunction,goodhandler)', ( xpcall(goodfunction,goodhandler) ) )
|
||||
print( 'xpcall(badfunction,goodhandler)', ( xpcall(badfunction,goodhandler) ) )
|
||||
print( 'xpcall(goodfunction,badhandler)', ( xpcall(goodfunction,badhandler) ) )
|
||||
print( 'xpcall(badfunction,badhandler)', ( xpcall(badfunction,badhandler) ) )
|
||||
print( 'xpcall(goodfunction,nil)', ( xpcall(goodfunction,nil) ) )
|
||||
print( 'xpcall(badfunction,nil)', ( xpcall(badfunction,nil) ) )
|
||||
print( 'xpcall(goodfunction)', ( pcall( function() return xpcall(goodfunction) end ) ) )
|
||||
print( 'xpcall(badfunction)', ( pcall( function() return xpcall(badfunction) end ) ) )
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
version: 1.0
|
||||
version: 1.0.1
|
||||
|
||||
Reference in New Issue
Block a user