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
|
Getting Started with LuaJ
|
||||||
|
|
||||||
</h1>
|
</h1>
|
||||||
James Roseborough, Ian Farmer, Version 1.0
|
James Roseborough, Ian Farmer, Version 1.0.1
|
||||||
<p>
|
<p>
|
||||||
<small>
|
<small>
|
||||||
Copyright © 2007-2009 Luaj.org.
|
Copyright © 2007-2009 Luaj.org.
|
||||||
@@ -36,6 +36,8 @@ Freely available under the terms of the
|
|||||||
<a href="#4">building</a>
|
<a href="#4">building</a>
|
||||||
·
|
·
|
||||||
<a href="#5">downloads</a>
|
<a href="#5">downloads</a>
|
||||||
|
·
|
||||||
|
<a href="#6">release notes</a>
|
||||||
|
|
||||||
<!-- ====================================================================== -->
|
<!-- ====================================================================== -->
|
||||||
<p>
|
<p>
|
||||||
@@ -334,3 +336,10 @@ and LuaForge:
|
|||||||
<a href="http://luaforge.net/frs/?group_id=457">LuaForge Luaj Project Area</a>
|
<a href="http://luaforge.net/frs/?group_id=457">LuaForge Luaj Project Area</a>
|
||||||
</pre>
|
</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: {
|
case PCALL: {
|
||||||
vm.checkany(1);
|
vm.checkany(1);
|
||||||
int n = vm.gettop();
|
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
|
if ( s == 0 ) { // success, results are on stack
|
||||||
vm.pushboolean( true );
|
vm.pushboolean( true );
|
||||||
vm.insert( 1 );
|
vm.insert( 1 );
|
||||||
@@ -210,26 +210,17 @@ public class BaseLib extends LFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case XPCALL: {
|
case XPCALL: {
|
||||||
LValue errfun = vm.checkany(3);
|
LValue errfun = vm.checkany(2);
|
||||||
vm.settop(1);
|
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
|
if ( s == 0 ) { // success, results are on stack
|
||||||
vm.pushboolean( true );
|
vm.pushboolean( true );
|
||||||
vm.insert( 1 );
|
vm.insert( 1 );
|
||||||
return -1;
|
return -1;
|
||||||
} else { // error, error message is on the stack
|
} else { // error, error message is on the stack
|
||||||
vm.pushlvalue( errfun );
|
vm.pushboolean( false );
|
||||||
vm.insert( 1 );
|
vm.insert( 1 );
|
||||||
s = vm.pcall( vm.gettop()-1, 1, 0 );
|
return 2;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case ERROR: {
|
case ERROR: {
|
||||||
@@ -489,7 +480,7 @@ public class BaseLib extends LFunction {
|
|||||||
try {
|
try {
|
||||||
while ( true ) {
|
while ( true ) {
|
||||||
setResult(vm,c);
|
setResult(vm,c);
|
||||||
if ( 0 != vm.pcall(0, 1, 0) ) {
|
if ( 0 != vm.pcall(0, 1) ) {
|
||||||
setErrorResult(vm, vm.tostring(2));
|
setErrorResult(vm, vm.tostring(2));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,14 +74,18 @@ public class LuaErrorException extends RuntimeException {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private static String addLineInfo(LuaState vm, String message, int level) {
|
private static String addLineInfo(LuaState vm, String message, int level) {
|
||||||
if ( level == 0 || message == null )
|
// add position information
|
||||||
return message;
|
|
||||||
if ( vm == null ) {
|
if ( vm == null ) {
|
||||||
if ( LThread.running != null )
|
if ( LThread.running != null )
|
||||||
vm = LThread.running.vm;
|
vm = LThread.running.vm;
|
||||||
else
|
else
|
||||||
vm = LuaState.mainState;
|
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 int cc = -1;
|
||||||
public CallInfo[] calls = new CallInfo[LUA_MINCALLS];
|
public CallInfo[] calls = new CallInfo[LUA_MINCALLS];
|
||||||
protected Stack upvals = new Stack();
|
protected Stack upvals = new Stack();
|
||||||
protected LFunction panic;
|
protected LValue errfunc;
|
||||||
|
|
||||||
static LuaState mainState;
|
static LuaState mainState;
|
||||||
public LTable _G;
|
public LTable _G;
|
||||||
@@ -362,24 +362,6 @@ public class LuaState extends Lua {
|
|||||||
* <a href="#lua_pcall"><code>lua_pcall</code></a> always removes the
|
* <a href="#lua_pcall"><code>lua_pcall</code></a> always removes the
|
||||||
* function and its arguments from the stack.
|
* 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>
|
* <p>
|
||||||
* The <a href="#lua_pcall"><code>lua_pcall</code></a> function returns
|
* 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
|
* 0 in case of success or one of the following error codes (defined in
|
||||||
@@ -399,7 +381,7 @@ public class LuaState extends Lua {
|
|||||||
*
|
*
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public int pcall( int nargs, int nreturns, int errfunc ) {
|
public int pcall( int nargs, int nreturns ) {
|
||||||
// save stack state
|
// save stack state
|
||||||
int oldtop = top;
|
int oldtop = top;
|
||||||
int oldbase = base;
|
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>
|
* Loads a Lua chunk. <span class="apii">[-0, +1, <em>-</em>]</span>
|
||||||
*
|
*
|
||||||
@@ -2362,6 +2384,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.
|
// Debug hooks.
|
||||||
// These should be obfuscated out when sethook is never called
|
// These should be obfuscated out when sethook is never called
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ public class lua {
|
|||||||
// load via "require"
|
// load via "require"
|
||||||
vm.getglobal("require");
|
vm.getglobal("require");
|
||||||
vm.pushstring(libname);
|
vm.pushstring(libname);
|
||||||
int status = vm.pcall(1, 0, 0);
|
int status = vm.pcall(1, 0);
|
||||||
if ( status == 0 )
|
if ( status == 0 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -58,3 +58,18 @@ for i = 0,4 do
|
|||||||
print( 'pcall(ge,i)', i, pcall(ge,i) )
|
print( 'pcall(ge,i)', i, pcall(ge,i) )
|
||||||
end
|
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