Clear stack before any lua call.

This commit is contained in:
James Roseborough
2007-11-19 22:30:55 +00:00
parent 3331abeb1d
commit 0d1aed5b5a
5 changed files with 118 additions and 30 deletions

View File

@@ -109,7 +109,7 @@ public class BaseLib extends LFunction {
vm.pushnil();
vm.pushstring( message );
}
private void checkargexists(LuaState vm, int index, int type) {
if ( vm.gettop() < index )
vm.error("bad argument #"+(index-1)+" to '?' ("+
@@ -120,8 +120,13 @@ public class BaseLib extends LFunction {
private void checkargtype(LuaState vm, int index, int type) {
checkargexists( vm, index, type );
if ( vm.type(index) != type )
vm.error("bad argument #"+(index-1)+" to '?' ("+Lua.TYPE_NAMES[type]+" expected, got "+vm.typename(index)+")");
int t = vm.type(index);
if ( t != type ) {
if ( type == Lua.LUA_TNUMBER && t == Lua.LUA_TSTRING && vm.isnumber(index) )
return;
vm.error("bad argument #"+(index-1)+" to '?' ("+
Lua.TYPE_NAMES[type]+" expected, got "+vm.typename(index)+")");
}
}
public boolean luaStackCall(LuaState vm) {
@@ -139,13 +144,15 @@ public class BaseLib extends LFunction {
}
case PAIRS:
case IPAIRS: {
LValue v = vm.topointer(2);
checkargtype(vm,2,Lua.LUA_TTABLE);
LTable v = vm.totable(2);
LValue r = v.luaPairs(id==PAIRS);
vm.resettop();
vm.pushlvalue( r );
break;
}
case GETMETATABLE: {
checkargexists(vm,2,Lua.LUA_TVALUE);
if ( 0 == vm.getmetatable(2) ) {
vm.resettop();
vm.pushnil();
@@ -156,8 +163,7 @@ public class BaseLib extends LFunction {
break;
}
case SETMETATABLE: {
if ( ! vm.istable(2) )
vm.error("bad argument #1 to '?' (table expected, got "+vm.typename(2)+")");
checkargtype(vm,2,Lua.LUA_TTABLE);
vm.setmetatable(2);
vm.remove(1);
break;
@@ -200,13 +206,14 @@ public class BaseLib extends LFunction {
break;
case TONUMBER: {
checkargexists(vm,2,Lua.LUA_TVALUE);
switch ( vm.type(2) ) {
case Lua.LUA_TNUMBER:
break;
case Lua.LUA_TSTRING:
LString s = vm.tolstring(2);
int base = 10;
if ( vm.gettop() >= 3 ) {
if ( vm.isnumber(3) ) {
base = vm.tointeger(3);
if ( base < 2 || base > 36 )
vm.error("bad argument #2 to '?' (base out of range)");
@@ -273,9 +280,8 @@ public class BaseLib extends LFunction {
break;
}
case SELECT: {
checkargexists(vm,2,Lua.LUA_TNUMBER);
int n = vm.gettop();
if ( n < 2 )
vm.error( "bad argument #1 to '?' (number expected, got no value)" );
if ( vm.isnumber(2) ) {
int index = vm.tointeger(2);
if ( index < 0 )
@@ -320,26 +326,27 @@ public class BaseLib extends LFunction {
load(vm, vm.topointer(2), vm.tostring(3));
break;
case TOSTRING: {
if ( vm.gettop() < 2 )
vm.error( "bad argument #1 to '?' (value expected)" );
checkargexists(vm,2,Lua.LUA_TVALUE);
LValue v = vm.topointer(2);
vm.resettop();
vm.pushlvalue( v.luaAsString() );
break;
}
case UNPACK: {
int n = vm.gettop();
if ( n < 2 )
vm.error( "bad argument #1 to '?' (table expected, got no value)" );
if ( ! vm.istable(2) )
vm.error( "bad argument #1 to '?' (table expected, got "+vm.typename(2)+")" );
checkargtype(vm,2,Lua.LUA_TTABLE);
LTable list = vm.totable(2);
int i = vm.tointeger(3);
int j = vm.tointeger(4);
if ( n <= 2 )
i = 1;
if ( n <= 3 )
int n = vm.gettop();
int i=1,j;
if ( n >= 3 ) {
checkargtype(vm,3,Lua.LUA_TNUMBER);
i = vm.tointeger(3);
}
if ( n >= 4 ) {
checkargtype(vm,4,Lua.LUA_TNUMBER);
j = vm.tointeger(4);
} else {
j = list.luaLength();
}
vm.resettop();
vm.checkstack(j+1-i);
for ( int k=i; k<=j; k++ )
@@ -347,7 +354,11 @@ public class BaseLib extends LFunction {
break;
}
case NEXT: {
setResult( vm, next(vm, vm.topointer(2), vm.tointeger(3)) );
checkargtype(vm,2,Lua.LUA_TTABLE);
LTable t = vm.totable(2);
LValue v = vm.topointer(3);
vm.resettop();
t.next(vm,v);
break;
}
default:
@@ -474,11 +485,4 @@ public class BaseLib extends LFunction {
closeSafely( baos );
}
}
private LValue next(LuaState vm, LValue table, int index) {
throw new LuaErrorException("next() not supported yet");
}
}

View File

@@ -78,4 +78,9 @@ public class LNumber extends LValue {
return new Short(toJavaShort());
}
/** Convert to a number if possible, or nil otherwise */
public LValue luaToNumber() {
return this;
}
}

View File

@@ -635,4 +635,59 @@ public class LTable extends LValue {
m_vector[j] = tmp;
}
/**
* Leave nil on top, or index,value pair
* @param vm
* @param index
*/
public void next(LuaState vm, LValue index) {
// look through vector first
int start = index.toJavaInt();
if ( start > 0 && start <= m_vector.length ) {
for ( int i=start; i<m_vector.length; i++ ) {
if ( m_vector[i] != LNil.NIL ) {
vm.pushinteger(i+1);
vm.pushlvalue(m_vector[i]);
return;
}
}
}
// look up key first
if ( index != LNil.NIL ) {
if ( m_hashEntries != 0 && (start <= 0 || start > m_vector.length) ) {
for ( int i=0; i<m_hashKeys.length; i++ ) {
if ( index.luaBinCmpUnknown( Lua.OP_EQ, m_hashKeys[i] ) ) {
start = m_vector.length+i+1;
break;
}
}
}
}
// start looking
if ( start < m_vector.length ) {
if ( m_arrayEntries != 0 ) {
for ( int i=start; i<m_vector.length; i++ ) {
if ( m_vector[i] != LNil.NIL ) {
vm.pushinteger(i+1);
vm.pushlvalue(m_vector[i]);
return;
}
}
start = m_vector.length;
}
if ( m_hashEntries != 0 ) {
for ( int i=start-m_vector.length; i<m_hashKeys.length; i++ ) {
if ( index.luaBinCmpUnknown( Lua.OP_EQ, m_hashKeys[i] ) ) {
vm.pushlvalue(m_hashKeys[i]);
vm.pushlvalue(m_hashValues[i]);
return;
}
}
}
}
vm.pushnil();
}
}

View File

@@ -302,4 +302,9 @@ public class LValue {
return 0;
}
/** Convert to a number if possible, or nil otherwise */
public LValue luaToNumber() {
return LNil.NIL;
}
}

View File

@@ -169,6 +169,8 @@ public class LuaState extends Lua {
}
calls[newcc] = new CallInfo(c, base, top, resultbase, nresults);
cc = newcc;
stackClear( top, base + c.p.maxstacksize );
}
/**
@@ -461,6 +463,12 @@ public class LuaState extends Lua {
top = newTop;
}
private final void stackClear(int startIndex, int endIndex) {
for (; startIndex < endIndex; startIndex++) {
stack[startIndex] = LNil.NIL;
}
}
/** execute instructions up to a yield, return, or call */
public void exec() {
if ( cc < 0 )
@@ -1460,9 +1468,20 @@ public class LuaState extends Lua {
* string convertible to a number, and 0&nbsp;otherwise.
*/
public boolean isnumber(int index) {
return type(index) == Lua.LUA_TNUMBER;
return tolnumber(index) != LNil.NIL;
}
/**
* Convert a value to an LNumber<span class="apii">[-0, +0, <em>-</em>]</span>
*
* <p>
* Returns an LNumber if the value at the given acceptable index is a number or a
* string convertible to a number, and LNil.NIL&nbsp;otherwise.
*/
public LValue tolnumber(int index) {
return topointer(index).luaToNumber();
}
/**
* Test if a value is a string <span class="apii">[-0, +0, <em>m</em>]</span>
*