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.pushnil();
vm.pushstring( message ); vm.pushstring( message );
} }
private void checkargexists(LuaState vm, int index, int type) { private void checkargexists(LuaState vm, int index, int type) {
if ( vm.gettop() < index ) if ( vm.gettop() < index )
vm.error("bad argument #"+(index-1)+" to '?' ("+ 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) { private void checkargtype(LuaState vm, int index, int type) {
checkargexists( vm, index, type ); checkargexists( vm, index, type );
if ( vm.type(index) != type ) int t = vm.type(index);
vm.error("bad argument #"+(index-1)+" to '?' ("+Lua.TYPE_NAMES[type]+" expected, got "+vm.typename(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) { public boolean luaStackCall(LuaState vm) {
@@ -139,13 +144,15 @@ public class BaseLib extends LFunction {
} }
case PAIRS: case PAIRS:
case IPAIRS: { case IPAIRS: {
LValue v = vm.topointer(2); checkargtype(vm,2,Lua.LUA_TTABLE);
LTable v = vm.totable(2);
LValue r = v.luaPairs(id==PAIRS); LValue r = v.luaPairs(id==PAIRS);
vm.resettop(); vm.resettop();
vm.pushlvalue( r ); vm.pushlvalue( r );
break; break;
} }
case GETMETATABLE: { case GETMETATABLE: {
checkargexists(vm,2,Lua.LUA_TVALUE);
if ( 0 == vm.getmetatable(2) ) { if ( 0 == vm.getmetatable(2) ) {
vm.resettop(); vm.resettop();
vm.pushnil(); vm.pushnil();
@@ -156,8 +163,7 @@ public class BaseLib extends LFunction {
break; break;
} }
case SETMETATABLE: { case SETMETATABLE: {
if ( ! vm.istable(2) ) checkargtype(vm,2,Lua.LUA_TTABLE);
vm.error("bad argument #1 to '?' (table expected, got "+vm.typename(2)+")");
vm.setmetatable(2); vm.setmetatable(2);
vm.remove(1); vm.remove(1);
break; break;
@@ -200,13 +206,14 @@ public class BaseLib extends LFunction {
break; break;
case TONUMBER: { case TONUMBER: {
checkargexists(vm,2,Lua.LUA_TVALUE);
switch ( vm.type(2) ) { switch ( vm.type(2) ) {
case Lua.LUA_TNUMBER: case Lua.LUA_TNUMBER:
break; break;
case Lua.LUA_TSTRING: case Lua.LUA_TSTRING:
LString s = vm.tolstring(2); LString s = vm.tolstring(2);
int base = 10; int base = 10;
if ( vm.gettop() >= 3 ) { if ( vm.isnumber(3) ) {
base = vm.tointeger(3); base = vm.tointeger(3);
if ( base < 2 || base > 36 ) if ( base < 2 || base > 36 )
vm.error("bad argument #2 to '?' (base out of range)"); vm.error("bad argument #2 to '?' (base out of range)");
@@ -273,9 +280,8 @@ public class BaseLib extends LFunction {
break; break;
} }
case SELECT: { case SELECT: {
checkargexists(vm,2,Lua.LUA_TNUMBER);
int n = vm.gettop(); int n = vm.gettop();
if ( n < 2 )
vm.error( "bad argument #1 to '?' (number expected, got no value)" );
if ( vm.isnumber(2) ) { if ( vm.isnumber(2) ) {
int index = vm.tointeger(2); int index = vm.tointeger(2);
if ( index < 0 ) if ( index < 0 )
@@ -320,26 +326,27 @@ public class BaseLib extends LFunction {
load(vm, vm.topointer(2), vm.tostring(3)); load(vm, vm.topointer(2), vm.tostring(3));
break; break;
case TOSTRING: { case TOSTRING: {
if ( vm.gettop() < 2 ) checkargexists(vm,2,Lua.LUA_TVALUE);
vm.error( "bad argument #1 to '?' (value expected)" );
LValue v = vm.topointer(2); LValue v = vm.topointer(2);
vm.resettop(); vm.resettop();
vm.pushlvalue( v.luaAsString() ); vm.pushlvalue( v.luaAsString() );
break; break;
} }
case UNPACK: { case UNPACK: {
int n = vm.gettop(); checkargtype(vm,2,Lua.LUA_TTABLE);
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)+")" );
LTable list = vm.totable(2); LTable list = vm.totable(2);
int i = vm.tointeger(3); int n = vm.gettop();
int j = vm.tointeger(4); int i=1,j;
if ( n <= 2 ) if ( n >= 3 ) {
i = 1; checkargtype(vm,3,Lua.LUA_TNUMBER);
if ( n <= 3 ) i = vm.tointeger(3);
}
if ( n >= 4 ) {
checkargtype(vm,4,Lua.LUA_TNUMBER);
j = vm.tointeger(4);
} else {
j = list.luaLength(); j = list.luaLength();
}
vm.resettop(); vm.resettop();
vm.checkstack(j+1-i); vm.checkstack(j+1-i);
for ( int k=i; k<=j; k++ ) for ( int k=i; k<=j; k++ )
@@ -347,7 +354,11 @@ public class BaseLib extends LFunction {
break; break;
} }
case NEXT: { 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; break;
} }
default: default:
@@ -474,11 +485,4 @@ public class BaseLib extends LFunction {
closeSafely( baos ); 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()); 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; 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; 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); calls[newcc] = new CallInfo(c, base, top, resultbase, nresults);
cc = newcc; cc = newcc;
stackClear( top, base + c.p.maxstacksize );
} }
/** /**
@@ -461,6 +463,12 @@ public class LuaState extends Lua {
top = newTop; 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 */ /** execute instructions up to a yield, return, or call */
public void exec() { public void exec() {
if ( cc < 0 ) if ( cc < 0 )
@@ -1460,9 +1468,20 @@ public class LuaState extends Lua {
* string convertible to a number, and 0&nbsp;otherwise. * string convertible to a number, and 0&nbsp;otherwise.
*/ */
public boolean isnumber(int index) { 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> * Test if a value is a string <span class="apii">[-0, +0, <em>m</em>]</span>
* *