Let all libraries implement invoke() instead of luaStackCall, correct off-by-one error on argument type check functions.

This commit is contained in:
James Roseborough
2009-04-09 16:27:01 +00:00
parent a414314114
commit 1d40b52348
11 changed files with 478 additions and 583 deletions

View File

@@ -120,112 +120,104 @@ public class BaseLib extends LFunction {
vm.pushstring( message );
}
public boolean luaStackCall(LuaState vm) {
public int invoke(LuaState vm) {
switch ( id ) {
case PRINT: {
int n = vm.gettop();
vm.getglobal("tostring");
for ( int i=2; i<=n; i++ ) {
for ( int i=1; i<=n; i++ ) {
vm.pushvalue(-1);
vm.pushvalue(i);
vm.call(1, 1);
if ( vm.type(-1) != Lua.LUA_TSTRING )
vm.error( "'tostring' must return a string to 'print'" );
if ( i > 2 )
if ( i > 1 )
STDOUT.print( "\t" );
STDOUT.print( vm.tostring(-1) );
vm.poplvalue();
}
STDOUT.println();
vm.resettop();
break;
return 0;
}
case IPAIRS: {
LTable t = vm.checktable(2);
vm.resettop();
LTable t = vm.checktable(1);
vm.pushfunction( inext );
vm.pushlvalue( t );
vm.pushinteger( 0 );
break;
return 3;
}
case PAIRS: {
LTable t = vm.checktable(2);
vm.resettop();
LTable t = vm.checktable(1);
vm.pushfunction( next );
vm.pushlvalue( t );
vm.pushnil();
break;
return 3;
}
case INEXT: {
int i = vm.checkint(3) + 1;
LTable t = vm.checktable(2);
int i = vm.checkint(2) + 1;
LTable t = vm.checktable(1);
LValue v = t.get(i);
vm.resettop();
if ( !v.isNil() ) {
vm.pushinteger(i);
vm.pushlvalue(v);
return 2;
}
break;
return 0;
}
case NEXT: {
LTable t = vm.checktable(2);
LValue k = vm.topointer(3);
LTable t = vm.checktable(1);
LValue k = vm.topointer(2);
vm.resettop();
t.next(vm,k,false);
break;
return -1;
}
case GETMETATABLE: {
vm.checkany(2);
if ( ! vm.getmetatable(2) ) {
vm.resettop();
vm.checkany(1);
if ( ! vm.getmetatable(1) ) {
vm.pushnil();
return 1;
} else {
vm.replace(1);
vm.settop(1);
vm.getfield(-1,LValue.TM_METATABLE);
if ( vm.isnil(-1) )
vm.pop(1);
else
vm.remove(1);
}
break;
return 1;
}
case SETMETATABLE: {
LTable t = vm.checktable(2);
LValue v = vm.checkany(3);
vm.argcheck(v.isTable() || v.isNil(), 3, "table or nil expected");
LTable t = vm.checktable(1);
LValue v = vm.checkany(2);
vm.argcheck(v.isTable() || v.isNil(), 2, "table or nil expected");
t = t.luaSetMetatable(v);
vm.resettop();
vm.pushlvalue(t);
break;
return 1;
}
case TYPE: {
LValue v = vm.checkany(2);
vm.resettop();
LValue v = vm.checkany(1);
vm.pushlstring( v.luaGetTypeName() );
break;
return 1;
}
case PCALL: {
vm.checkany(2);
vm.checkany(1);
int n = vm.gettop();
int s = vm.pcall( n-2, Lua.LUA_MULTRET, 0 );
if ( s == 0 ) { // success, results are on stack above the pcall
vm.remove( 1 );
int s = vm.pcall( n-1, Lua.LUA_MULTRET, 0 );
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.pushboolean( false );
vm.insert( 1 );
vm.insert( -2 );
return 2;
}
break;
}
case XPCALL: {
LValue errfun = vm.checkany(3);
vm.settop(2);
vm.settop(1);
int s = vm.pcall( 0, Lua.LUA_MULTRET, 0 );
if ( s == 0 ) { // success, results are on stack above the xpcall
if ( s == 0 ) { // success, results are on stack
vm.pushboolean( true );
vm.replace( 1 );
vm.insert( 1 );
return -1;
} else { // error, error message is on the stack
vm.pushlvalue( errfun );
vm.insert( 1 );
@@ -233,113 +225,105 @@ public class BaseLib extends LFunction {
if ( s == 0 ) {
vm.pushboolean( false );
vm.insert( 1 );
return -1;
} else { // error in error handler
vm.resettop();
vm.pushboolean(false);
vm.pushstring("error in error handling");
return 2;
}
}
break;
}
case ERROR: {
vm.error(vm.optstring(2,null), vm.optint(3,1));
break;
vm.error(vm.optstring(1,null), vm.optint(2,1));
return 0;
}
case ASSERT: {
if ( ! vm.toboolean(2) )
vm.error( vm.optstring(3,"assertion failed!") );
vm.remove(1);
break;
if ( ! vm.toboolean(1) )
vm.error( vm.optstring(2,"assertion failed!") );
return -1;
}
case LOADFILE:
loadfile(vm, vm.optstring(2,null));
break;
loadfile(vm, vm.optstring(1,null));
return -1;
case TONUMBER: {
int base = vm.optint(3, 10);
int base = vm.optint(2, 10);
if (base == 10) { /* standard conversion */
vm.checkany(2);
LValue v = vm.tolnumber(2);
vm.resettop();
vm.checkany(1);
LValue v = vm.tolnumber(1);
vm.pushlvalue(v);
return 1;
} else {
if ( base < 2 || base > 36 )
vm.typerror(3, "base out of range");
LString s = vm.checklstring(2);
vm.resettop();
vm.argerror(2, "base out of range");
LString s = vm.checklstring(1);
vm.pushlvalue( s.luaToNumber(base) );
return 1;
}
break;
}
case RAWEQUAL: {
LValue a = vm.checkany(2);
LValue b = vm.checkany(3);
vm.resettop();
LValue a = vm.checkany(1);
LValue b = vm.checkany(2);
vm.pushboolean(a == b);
break;
return 1;
}
case RAWGET: {
LTable t = vm.checktable(2);
LValue k = vm.checkany(3);
vm.resettop();
LTable t = vm.checktable(1);
LValue k = vm.checkany(2);
vm.pushlvalue( t.get( k ) );
break;
return 1;
}
case RAWSET: {
LTable t = vm.checktable(2);
LValue k = vm.checkany(3);
LValue v = vm.checkany(4);
LTable t = vm.checktable(1);
LValue k = vm.checkany(2);
LValue v = vm.checkany(3);
t.put( k, v );
vm.resettop();
vm.pushlvalue(t);
break;
return 1;
}
case GETFENV: {
LValue f = getfunc(vm, true);
vm.resettop();
vm.pushlvalue(f.luaGetEnv(vm._G));
break;
return 1;
}
case SETFENV: {
LTable t = vm.checktable(3);
LValue f = getfunc(vm, false);
if ( vm.isnumber(2) && vm.tointeger(2) == 0 ) {
LTable t = vm.checktable(2);
if ( vm.isnumber(1) && vm.tointeger(1) == 0 ) {
vm._G = t;
} else if ( (!(f instanceof LClosure)) || ! f.luaSetEnv(t) ) {
} else {
LValue f = getfunc(vm, false);
if ( (!(f instanceof LClosure)) || ! f.luaSetEnv(t) )
vm.error( "'setfenv' cannot change environment of given object" );
}
vm.resettop();
vm.pushlvalue(f);
break;
return 1;
}
}
case SELECT: {
vm.checkany(2);
vm.checkany(1);
int n = vm.gettop();
if ( vm.isnumber(2) ) {
int index = vm.tolnumber(2).toJavaInt();
if ( vm.isnumber(1) ) {
int index = vm.tolnumber(1).toJavaInt();
if ( index < 0 )
index += n-1;
index += n;
if ( index <= 0 )
vm.typerror( 2, "index out of range" );
vm.argerror( 1, "index out of range" );
if ( index >= n )
vm.resettop();
return 0;
else {
for ( int i=0; i<=index; i++ )
vm.remove(1);
return n-index;
}
} else if ( vm.checkstring(2).equals( "#" ) ) {
vm.resettop();
vm.pushnumber( n - 2 );
} else if ( vm.checkstring(1).equals( "#" ) ) {
vm.pushnumber( n - 1 );
return 1;
} else {
vm.typerror(2,"expected number or '#'");
vm.typerror(1,"expected number or '#'");
return 0;
}
break;
}
case COLLECTGARBAGE: {
String s = vm.optstring(2, "collect");
String s = vm.optstring(1, "collect");
int result = 0;
vm.resettop();
if ( "collect".equals(s) )
System.gc();
else if ( "count".equals(s) ) {
@@ -347,33 +331,32 @@ public class BaseLib extends LFunction {
long used = rt.totalMemory() - rt.freeMemory();
result = (int) (used >> 10);
} else {
vm.typerror(2,"gc op");
vm.argerror(2,"gc op");
}
vm.pushnumber(result);
break;
return 1;
}
case DOFILE:
dofile(vm);
break;
return -1;
case LOADSTRING:
loadstring(vm, vm.checklstring(2), vm.optstring(3,"(string)"));
break;
loadstring(vm, vm.checklstring(1), vm.optstring(2,"(string)"));
return -1;
case LOAD:
load(vm);
break;
return -1;
case TOSTRING: {
LValue v = vm.checkany(2);
vm.resettop();
LValue v = vm.checkany(1);
vm.pushlvalue( v.luaAsString() );
break;
return 1;
}
case UNPACK: {
LTable list = vm.checktable(2);
LTable list = vm.checktable(1);
int n = vm.gettop();
int i = vm.optint(3,1);
int i = vm.optint(2,1);
int j;
if ( n >= 4 ) {
j = vm.checkint(4);
if ( n >= 3 ) {
j = vm.checkint(3);
} else {
j = list.luaLength();
}
@@ -381,21 +364,21 @@ public class BaseLib extends LFunction {
vm.checkstack(j+1-i);
for ( int k=i; k<=j; k++ )
vm.pushlvalue(list.get(k));
break;
return -1;
}
default:
LuaState.vmerror( "bad base id" );
return 0;
}
return false;
}
private static LValue getfunc (LuaState vm, boolean opt) {
if ( vm.isfunction(2) )
return vm.tofunction(2);
if ( vm.isfunction(1) )
return vm.tofunction(1);
else {
int level = opt? vm.optint(2, 1): vm.checkint(2);
vm.argcheck(level >= 0, 2, "level must be non-negative");
vm.argcheck(level-1 <= vm.cc, 2, "invalid level");
int level = opt? vm.optint(1, 1): vm.checkint(1);
vm.argcheck(level >= 0, 1, "level must be non-negative");
vm.argcheck(level-1 <= vm.cc, 1, "invalid level");
CallInfo ci = vm.getStackFrame(level-1);
if ( ci == null || ci.closure == null )
return LNil.NIL;
@@ -483,7 +466,7 @@ public class BaseLib extends LFunction {
// if load succeeds, return 0 for success, 1 for error (as per lua spec)
private void dofile( LuaState vm ) {
String filename = vm.optstring(2,null);
String filename = vm.optstring(1,null);
if ( loadfile( vm, filename ) ) {
vm.call(0, 0);
} else {

View File

@@ -21,7 +21,6 @@
******************************************************************************/
package org.luaj.lib;
import org.luaj.vm.LClosure;
import org.luaj.vm.LFunction;
import org.luaj.vm.LTable;
import org.luaj.vm.LThread;
@@ -79,21 +78,21 @@ public class CoroutineLib extends LFunction {
this.thread = thread;
}
public boolean luaStackCall( LuaState vm ) {
public int invoke( LuaState vm ) {
switch ( id ) {
case INSTALL: {
install(vm._G);
break;
return 0;
}
case CREATE: {
LFunction c = vm.checkfunction(2);
LFunction c = vm.checkfunction(1);
vm.pushlvalue( new LThread( c, c.luaGetEnv(vm._G) ) );
break;
return 1;
}
case RESUME: {
LThread t = vm.checkthread(2);
t.resumeFrom( vm, vm.gettop()-2 );
return false;
LThread t = vm.checkthread(1);
t.resumeFrom( vm, vm.gettop()-1 );
return -1;
}
case RUNNING: {
LThread r = LThread.getRunning();
@@ -102,39 +101,41 @@ public class CoroutineLib extends LFunction {
} else {
vm.pushnil();
}
break;
return 1;
}
case STATUS: {
vm.pushstring( vm.checkthread(2).getStatus() );
break;
vm.pushstring( vm.checkthread(1).getStatus() );
return 1;
}
case WRAP: {
LFunction c = vm.checkfunction(2);
LFunction c = vm.checkfunction(1);
vm.pushlvalue( new CoroutineLib(WRAPPED,new LThread(c, c.luaGetEnv(vm._G))) );
break;
return 1;
}
case YIELD: {
LThread r = LThread.getRunning();
if ( r == null )
if ( r == null ) {
vm.error("main thread can't yield");
else {
return r.yield();
return 0;
}
r.yield();
return -1;
}
case WRAPPED: {
LThread t = this.thread;
t.resumeFrom( vm, vm.gettop()-1 );
if ( vm.toboolean(1) )
t.resumeFrom( vm, vm.gettop() );
if ( vm.toboolean(1) ) {
vm.remove(1);
else
return -1;
} else {
vm.error( vm.tostring(2) );
return false;
return 0;
}
}
default: {
LuaState.vmerror( "bad coroutine id" );
return 0;
}
}
vm.insert(1);
vm.settop(1);
return false;
}
}

View File

@@ -108,88 +108,74 @@ public class DebugLib extends LFunction {
return NAMES[id]+"()";
}
public boolean luaStackCall( LuaState vm ) {
public int invoke( LuaState vm ) {
switch ( id ) {
case INSTALL:
install(vm);
break;
return 0;
case DEBUG:
debug(vm);
break;
return debug(vm);
case GETFENV:
getfenv(vm);
break;
return getfenv(vm);
case GETHOOK:
gethook(vm);
break;
return gethook(vm);
case GETINFO:
getinfo(vm);
break;
return getinfo(vm);
case GETLOCAL:
getlocal(vm);
break;
return getlocal(vm);
case GETMETATABLE:
getmetatable(vm);
break;
return getmetatable(vm);
case GETREGISTRY:
getregistry(vm);
break;
return getregistry(vm);
case GETUPVALUE:
getupvalue(vm);
break;
return getupvalue(vm);
case SETFENV:
setfenv(vm);
break;
return setfenv(vm);
case SETHOOK:
sethook(vm);
break;
return sethook(vm);
case SETLOCAL:
setlocal(vm);
break;
return setlocal(vm);
case SETMETATABLE:
setmetatable(vm);
break;
return setmetatable(vm);
case SETUPVALUE:
setupvalue(vm);
break;
return setupvalue(vm);
case TRACEBACK:
traceback(vm);
break;
return traceback(vm);
default:
LuaState.vmerror( "bad package id" );
return 0;
}
return false;
}
// j2se subclass may wish to override and provide actual console here.
// j2me platform has not System.in to provide console.
protected void debug(LuaState vm) {
vm.resettop();
protected int debug(LuaState vm) {
return 0;
}
protected void gethook(LuaState vm) {
protected int gethook(LuaState vm) {
LuaState threadVm = vm;
if ( vm.gettop() >= 2 )
threadVm = vm.checkthread(2).vm;
vm.resettop();
threadVm = vm.checkthread(1).vm;
vm.pushlvalue(threadVm.gethook());
vm.pushinteger(threadVm.gethookmask());
vm.pushinteger(threadVm.gethookcount());
return 3;
}
protected LuaState optthreadvm(LuaState vm, int index) {
if ( ! vm.isthread(2) )
if ( ! vm.isthread(index) )
return vm;
LuaState threadVm = vm.checkthread(2).vm;
vm.remove(2);
LuaState threadVm = vm.checkthread(index).vm;
vm.remove(index);
return threadVm;
}
protected void sethook(LuaState vm) {
LuaState threadVm = optthreadvm(vm, 2);
LFunction func = vm.isnoneornil(2)? null: vm.checkfunction(2);
String str = vm.optstring(3,"");
int count = vm.optint(4,0);
protected int sethook(LuaState vm) {
LuaState threadVm = optthreadvm(vm, 1);
LFunction func = vm.isnoneornil(1)? null: vm.checkfunction(2);
String str = vm.optstring(2,"");
int count = vm.optint(3,0);
int mask = 0;
for ( int i=0; i<str.length(); i++ )
switch ( str.charAt(i) ) {
@@ -198,41 +184,40 @@ public class DebugLib extends LFunction {
case 'r': mask |= LuaState.LUA_MASKRET; break;
}
threadVm.sethook(func, mask, count);
vm.resettop();
return 0;
}
protected void getfenv(LuaState vm) {
LValue object = vm.topointer(2);
protected int getfenv(LuaState vm) {
LValue object = vm.topointer(1);
LValue env = object.luaGetEnv(null);
vm.resettop();
vm.pushlvalue(env!=null? env: LNil.NIL);
return 1;
}
protected void setfenv(LuaState vm) {
LValue object = vm.topointer(2);
LTable table = vm.checktable(3);
protected int setfenv(LuaState vm) {
LValue object = vm.topointer(1);
LTable table = vm.checktable(2);
object.luaSetEnv(table);
vm.settop(1);
return 1;
}
protected void getinfo(LuaState vm) {
LuaState threadVm = optthreadvm(vm, 2);
String what = vm.optstring(3, "nSluf");
protected int getinfo(LuaState vm) {
LuaState threadVm = optthreadvm(vm, 1);
String what = vm.optstring(2, "nSluf");
// find the stack info
StackInfo si;
if ( vm.isnumber(2) ) {
int level = vm.tointeger(2);
if ( vm.isnumber(1) ) {
int level = vm.tointeger(1);
si = getstackinfo(threadVm, level, 1)[0];
if ( si == null ) {
vm.resettop();
return;
return 0;
}
} else {
LFunction func = vm.checkfunction(2);
LFunction func = vm.checkfunction(1);
si = findstackinfo(threadVm, func);
}
vm.resettop();
// look up info
LTable info = new LTable();
@@ -288,75 +273,75 @@ public class DebugLib extends LFunction {
}
}
}
return 1;
}
protected void getlocal(LuaState vm) {
LuaState threadVm = optthreadvm(vm, 2);
int level = vm.checkint(2);
int local = vm.checkint(3);
protected int getlocal(LuaState vm) {
LuaState threadVm = optthreadvm(vm, 1);
int level = vm.checkint(1);
int local = vm.checkint(2);
StackInfo si = getstackinfo(threadVm, level, 1)[0];
CallInfo ci = (si!=null? si.luainfo: null);
LPrototype p = (ci!=null? ci.closure.p: null);
LString name = (p!=null? p.getlocalname(local, ci.pc>0? ci.pc-1: 0): null);
if ( name != null ) {
LValue value = threadVm.stack[ci.base+(local-1)];
vm.resettop();
vm.pushlvalue( name );
vm.pushlvalue( value );
return 2;
} else {
vm.resettop();
vm.pushnil();
return 1;
}
}
protected void setlocal(LuaState vm) {
LuaState threadVm = optthreadvm(vm, 2);
int level = vm.checkint(2);
int local = vm.checkint(3);
LValue value = vm.topointer(4);
protected int setlocal(LuaState vm) {
LuaState threadVm = optthreadvm(vm, 1);
int level = vm.checkint(1);
int local = vm.checkint(2);
LValue value = vm.topointer(3);
StackInfo si = getstackinfo(threadVm, level, 1)[0];
CallInfo ci = (si!=null? si.luainfo: null);
LPrototype p = (ci!=null? ci.closure.p: null);
LString name = (p!=null? p.getlocalname(local, ci.pc>0? ci.pc-1: 0): null);
if ( name != null ) {
threadVm.stack[ci.base+(local-1)] = value;
vm.resettop();
vm.pushlvalue(name);
} else {
vm.resettop();
vm.pushnil();
}
return 1;
}
protected void getmetatable(LuaState vm) {
LValue object = vm.topointer(2);
vm.resettop();
protected int getmetatable(LuaState vm) {
LValue object = vm.topointer(1);
LValue mt = object.luaGetMetatable();
if ( mt != null )
vm.pushlvalue( object.luaGetMetatable() );
else
vm.pushnil();
return 1;
}
protected void setmetatable(LuaState vm) {
LValue object = vm.topointer(2);
protected int setmetatable(LuaState vm) {
LValue object = vm.topointer(1);
try {
if ( ! vm.isnoneornil(3) )
if ( ! vm.isnoneornil(2) )
object.luaSetMetatable(vm.checktable(3));
else
object.luaSetMetatable(null);
vm.resettop();
vm.pushboolean(true);
return 1;
} catch ( LuaErrorException e ) {
vm.resettop();
vm.pushboolean(false);
vm.pushstring(e.toString());
return 2;
}
}
protected void getregistry(LuaState vm) {
vm.resettop();
protected int getregistry(LuaState vm) {
vm.pushlvalue( new LTable() );
return 1;
}
private LString findupvalue(LClosure c, int up) {
@@ -369,9 +354,9 @@ public class DebugLib extends LFunction {
return null;
}
protected void getupvalue(LuaState vm) {
LFunction func = vm.checkfunction(2);
int up = vm.checkint(3);
protected int getupvalue(LuaState vm) {
LFunction func = vm.checkfunction(1);
int up = vm.checkint(2);
vm.resettop();
if ( func instanceof LClosure ) {
LClosure c = (LClosure) func;
@@ -379,16 +364,17 @@ public class DebugLib extends LFunction {
if ( name != null ) {
vm.pushlstring(name);
vm.pushlvalue(c.upVals[up-1].getValue());
return;
return 2;
}
}
vm.pushnil();
return 1;
}
protected void setupvalue(LuaState vm) {
LFunction func = vm.checkfunction(2);
int up = vm.checkint(3);
LValue value = vm.topointer(4);
protected int setupvalue(LuaState vm) {
LFunction func = vm.checkfunction(1);
int up = vm.checkint(2);
LValue value = vm.topointer(3);
vm.resettop();
if ( func instanceof LClosure ) {
LClosure c = (LClosure) func;
@@ -396,18 +382,19 @@ public class DebugLib extends LFunction {
if ( name != null ) {
c.upVals[up-1].setValue(value);
vm.pushlstring(name);
return;
return 1;
}
}
vm.pushnil();
return 1;
}
protected void traceback(LuaState vm) {
LuaState threadVm = optthreadvm(vm, 2);
protected int traceback(LuaState vm) {
LuaState threadVm = optthreadvm(vm, 1);
String message = "";
int level = vm.optint(3,1);
if ( ! vm.isnoneornil(2) )
message = vm.checkstring(2)+"\n";
int level = vm.optint(2,1);
if ( ! vm.isnoneornil(1) )
message = vm.checkstring(1)+"\n";
StackInfo[] s = getstackinfo(threadVm, level, 10);
StringBuffer sb = new StringBuffer("stack traceback:");
for ( int i=0; i<s.length; i++ ) {
@@ -419,8 +406,8 @@ public class DebugLib extends LFunction {
sb.append( si.tracename() );
}
}
vm.resettop();
vm.pushstring(message+sb);
return 1;
}
// =======================================================

View File

@@ -214,7 +214,7 @@ public class IoLib extends LFunction {
return LNil.NIL;
}
public boolean luaStackCall( LuaState vm ) {
public int invoke( LuaState vm ) {
File f;
int n;
try {
@@ -222,49 +222,47 @@ public class IoLib extends LFunction {
/* Load the table library dynamically */
case INSTALL:
initialize(vm._G);
break;
return 0;
case IO_CLOSE:
f = vm.isnoneornil(2)?
f = vm.isnoneornil(1)?
output(vm):
checkfile(vm,2);
checkfile(vm,1);
checkopen(vm, f);
ioclose(vm,f);
break;
case IO_FLUSH:
checkopen(vm,output(vm));
OUTPUT.flush();
vm.resettop();
vm.pushboolean(true);
break;
return 1;
case IO_INPUT:
INPUT = vm.isnoneornil(2)?
INPUT = vm.isnoneornil(1)?
input(vm):
vm.isstring(2)?
ioopenfile(vm,vm.checkstring(2),"r"):
checkfile(vm,2);
vm.isstring(1)?
ioopenfile(vm,vm.checkstring(1),"r"):
checkfile(vm,1);
setresult(vm, INPUT);
break;
case IO_LINES:
INPUT = vm.isnoneornil(2)?
INPUT = vm.isnoneornil(1)?
input(vm):
ioopenfile(vm,vm.checkstring(2),"r");
ioopenfile(vm,vm.checkstring(1),"r");
checkopen(vm, INPUT);
vm.resettop();
vm.pushlvalue(lines(vm,INPUT));
break;
return 1;
case IO_OPEN:
setresult(vm, rawopenfile(vm.checkstring(2), vm.optstring(3,"r")));
setresult(vm, rawopenfile(vm.checkstring(1), vm.optstring(2,"r")));
break;
case IO_OUTPUT:
OUTPUT = vm.isnoneornil(2)?
OUTPUT = vm.isnoneornil(1)?
output(vm):
vm.isstring(2)?
ioopenfile(vm,vm.checkstring(2),"w"):
checkfile(vm,2);
vm.isstring(1)?
ioopenfile(vm,vm.checkstring(1),"w"):
checkfile(vm,1);
setresult(vm, OUTPUT);
break;
case IO_POPEN:
setresult(vm, openProgram(vm.checkstring(2),vm.optstring(3, "r")));
setresult(vm, openProgram(vm.checkstring(1),vm.optstring(2, "r")));
break;
case IO_READ:
checkopen(vm, INPUT);
@@ -274,54 +272,49 @@ public class IoLib extends LFunction {
setresult(vm, tmpFile());
break;
case IO_TYPE:
f = optfile(vm,2);
vm.resettop();
f = optfile(vm,1);
if ( f != null )
vm.pushstring(f.isclosed()? "closed file": "file");
else
vm.pushnil();
break;
return 1;
case IO_WRITE:
checkopen(vm, output(vm));
iowrite( vm, OUTPUT );
break;
case FILE_CLOSE:
f = checkfile(vm,2);
f = checkfile(vm,1);
ioclose(vm, f);
break;
case FILE_FLUSH:
f = checkfile(vm,2);
f = checkfile(vm,1);
f.flush();
vm.resettop();
vm.pushboolean(true);
break;
return 1;
case FILE_LINES:
f = checkfile(vm,2);
vm.resettop();
f = checkfile(vm,1);
vm.pushlvalue(lines(vm,f));
break;
return 1;
case FILE_READ:
f = checkfile(vm,2);
vm.remove(2);
f = checkfile(vm,1);
vm.remove(1);
ioread(vm, f);
break;
case FILE_SEEK:
f = checkfile(vm,2);
vm.remove(2);
n = f.seek(vm.optstring(2,"cur"),vm.optint(3, 0));
vm.resettop();
f = checkfile(vm,1);
vm.remove(1);
n = f.seek(vm.optstring(1,"cur"),vm.optint(2, 0));
vm.pushinteger(n);
break;
return 1;
case FILE_SETVBUF:
f = checkfile(vm,2);
vm.remove(2);
f.setvbuf(vm.checkstring(2),vm.optint(3, 1024));
vm.resettop();
f = checkfile(vm,1);
vm.remove(1);
f.setvbuf(vm.checkstring(1),vm.optint(2, 1024));
vm.pushboolean(true);
break;
return 1;
case FILE_WRITE:
f = checkfile(vm,2);
vm.remove(2);
f = checkfile(vm,1);
vm.remove(1);
iowrite( vm, f );
break;
default:
@@ -330,7 +323,7 @@ public class IoLib extends LFunction {
} catch ( IOException ioe ) {
seterrorresult(vm,ioe);
}
return false;
return -1;
}
private static void ioclose(LuaState vm, File f) throws IOException {
@@ -373,7 +366,7 @@ public class IoLib extends LFunction {
}
private static void iowrite(LuaState vm, File f) throws IOException {
for ( int i=2, n=vm.gettop(); i<=n; i++ )
for ( int i=1, n=vm.gettop(); i<=n; i++ )
f.write( vm.checklstring(i) );
vm.resettop();
vm.pushboolean(true);
@@ -381,7 +374,7 @@ public class IoLib extends LFunction {
private static void ioread(LuaState vm, File f) throws IOException {
int i,n=vm.gettop();
for ( i=2; i<=n; i++ ) {
for ( i=1; i<=n; i++ ) {
if ( vm.isnumber(i) ) {
vm.pushlvalue(freadbytes(f,vm.tointeger(i)));
} else {

View File

@@ -25,10 +25,7 @@ import java.util.Random;
import org.luaj.vm.LDouble;
import org.luaj.vm.LFunction;
import org.luaj.vm.LInteger;
import org.luaj.vm.LNumber;
import org.luaj.vm.LTable;
import org.luaj.vm.LValue;
import org.luaj.vm.LuaState;
import org.luaj.vm.Platform;
@@ -142,105 +139,89 @@ public class MathLib extends LFunction {
vm.pushlvalue( LDouble.valueOf(d) );
}
private static void setResult( LuaState vm, int i ) {
vm.resettop();
vm.pushlvalue( LInteger.valueOf(i) );
}
private static void setResult(LuaState vm, LNumber mathop) {
vm.resettop();
vm.pushlvalue( mathop );
}
public boolean luaStackCall( LuaState vm ) {
public int invoke(LuaState vm) {
if ( id > LAST_DOUBLE_ARG ) {
setResult( vm, platform.mathop(id, vm.checknumber(2) ) );
vm.pushlvalue( platform.mathop(id, vm.checknumber(1) ) );
return 1;
} else if ( id > LAST_IRREGULAR ) {
setResult( vm, platform.mathop(id, vm.checknumber(2), vm.checknumber(3) ) );
vm.pushlvalue( platform.mathop(id, vm.checknumber(1), vm.checknumber(2) ) );
return 1;
} else {
switch ( id ) {
case INSTALL:
install( vm._G );
break;
return 0;
case MAX: {
int n = vm.gettop();
double x = vm.checkdouble(2);
for ( int i=3; i<=n; i++ )
double x = vm.checkdouble(1);
for ( int i=2; i<=n; i++ )
x = Math.max(x, vm.checkdouble(i));
setResult( vm, x );
break;
vm.pushnumber( x );
return 1;
}
case MIN: {
int n = vm.gettop();
double x = vm.checkdouble(2);
for ( int i=3; i<=n; i++ )
double x = vm.checkdouble(1);
for ( int i=2; i<=n; i++ )
x = Math.min(x, vm.checkdouble(i));
setResult(vm,x);
break;
vm.pushnumber( x );
return 1;
}
case MODF: {
double x = vm.checkdouble(2);
double x = vm.checkdouble(1);
double intPart = ( x > 0 ) ? Math.floor( x ) : Math.ceil( x );
double fracPart = x - intPart;
vm.resettop();
vm.pushnumber( intPart );
vm.pushnumber( fracPart );
break;
return 2;
}
case CEIL:
setResult( vm, (int) Math.ceil( vm.checkdouble(2) ) );
break;
vm.pushnumber( Math.ceil( vm.checkdouble(1) ) );
return 1;
case FLOOR:
setResult( vm, (int) Math.floor( vm.checkdouble(2) ) );
break;
vm.pushnumber( Math.floor( vm.checkdouble(1) ) );
return 1;
case FREXP: {
long bits = Double.doubleToLongBits( vm.checkdouble(2) );
vm.resettop();
long bits = Double.doubleToLongBits( vm.checkdouble(1) );
vm.pushnumber( ((bits & (~(-1L<<52))) + (1L<<52)) * ((bits >= 0)? (.5 / (1L<<52)): (-.5 / (1L<<52))) );
vm.pushinteger( (((int) (bits >> 52)) & 0x7ff) - 1022 );
break;
return 2;
}
case LDEXP: {
double m = vm.checkdouble(2);
int e = vm.checkint(3);
vm.resettop();
double m = vm.checkdouble(1);
int e = vm.checkint(2);
vm.pushnumber( m * Double.longBitsToDouble(((long)(e+1023)) << 52) );
break;
return 1;
}
case RANDOM: {
if ( random == null )
random = new Random(1);
switch ( vm.gettop() ) {
case 1:
vm.resettop();
case 0:
vm.pushnumber(random.nextDouble());
break;
case 2: {
int m = vm.checkint(2);
return 1;
case 1: {
int m = vm.checkint(1);
vm.argcheck(1<=m, 1, "interval is empty");
vm.resettop();
vm.pushinteger(1+random.nextInt(m));
break;
return 1;
}
default: {
int m = vm.checkint(2);
int n = vm.checkint(3);
int m = vm.checkint(1);
int n = vm.checkint(2);
vm.argcheck(m<=n, 2, "interval is empty");
vm.resettop();
vm.pushinteger(m+random.nextInt(n+1-m));
break;
return 1;
}
}
break;
}
case RSEED:
random = new Random( vm.checkint(2) );
vm.resettop();
break;
random = new Random( vm.checkint(1) );
return 0;
default:
LuaState.vmerror( "bad math id" );
return 0;
}
}
return false;
}
}

View File

@@ -122,7 +122,7 @@ public class OsLib extends LFunction {
return NAMES[id]+"()";
}
public boolean luaStackCall( LuaState vm ) {
public int invoke( LuaState vm ) {
LValue v;
long t,t2;
int c;
@@ -131,72 +131,62 @@ public class OsLib extends LFunction {
switch ( id ) {
case INSTALL:
install(vm._G, this);
break;
return 0;
case CLOCK:
vm.resettop();
vm.pushnumber(clock());
break;
return 1;
case DATE:
s = vm.optstring(2, null);
t = vm.optlong(3,-1);
vm.resettop();
s = vm.optstring(1, null);
t = vm.optlong(2,-1);
vm.pushlvalue( date(s, t==-1? System.currentTimeMillis(): t) );
break;
return 1;
case DIFFTIME:
t2 = vm.checklong(2);
t = vm.checklong(3);
vm.resettop();
t2 = vm.checklong(1);
t = vm.checklong(2);
vm.pushnumber(difftime(t2,t));
break;
return 1;
case EXECUTE:
c = execute(vm.optstring(2, null));
vm.resettop();
c = execute(vm.optstring(1, null));
vm.pushinteger(c);
break;
return 1;
case EXIT:
exit(vm.optint(2, 0));
break;
exit(vm.optint(1, 0));
return 0;
case GETENV:
s = getenv(vm.checkstring(2));
vm.resettop();
s = getenv(vm.checkstring(1));
vm.pushstring(s);
break;
return 1;
case REMOVE:
remove(vm.checkstring(2));
vm.resettop();
remove(vm.checkstring(1));
vm.pushboolean(true);
break;
return 1;
case RENAME:
rename(vm.checkstring(2), vm.checkstring(3));
vm.resettop();
rename(vm.checkstring(1), vm.checkstring(2));
vm.pushboolean(true);
break;
return 1;
case SETLOCALE:
s = setlocale(vm.optstring(2,null), vm.optstring(3, "all"));
vm.resettop();
s = setlocale(vm.optstring(1,null), vm.optstring(2, "all"));
if ( s != null )
vm.pushstring(s);
else
vm.pushnil();
break;
return 1;
case TIME:
t = time(vm.isnoneornil(2)? null: vm.checktable(2));
vm.resettop();
t = time(vm.isnoneornil(1)? null: vm.checktable(1));
vm.pushnumber(t);
break;
return 1;
case TMPNAME:
vm.resettop();
vm.pushstring(tmpname());
break;
return 1;
default:
LuaState.vmerror( "bad os id" );
return 0;
}
} catch ( IOException e ) {
vm.resettop();
vm.pushnil();
vm.pushstring(e.getMessage());
return 2;
}
return false;
}
/**

View File

@@ -115,45 +115,38 @@ public class PackageLib extends LFunction {
return NAMES[id]+"()";
}
public boolean luaStackCall( LuaState vm ) {
public int invoke( LuaState vm ) {
switch ( id ) {
case INSTALL:
install(vm._G);
break;
return 0;
case MODULE:
module(vm);
break;
return module(vm);
case REQUIRE:
require(vm);
break;
return require(vm);
case LOADLIB:
loadlib(vm);
break;
return loadlib(vm);
case SEEALL: {
LTable t = vm.checktable(2);
LTable t = vm.checktable(1);
LTable m = t.luaGetMetatable();
if ( m == null )
t.luaSetMetatable(m = new LTable());
m.put(__INDEX, vm._G);
vm.resettop();
break;
return 0;
}
case PRELOAD_LOADER: {
loader_preload(vm);
break;
return loader_preload(vm);
}
case LUA_LOADER: {
loader_Lua(vm);
break;
return loader_Lua(vm);
}
case JAVA_LOADER: {
loader_Java(vm);
break;
return loader_Java(vm);
}
default:
LuaState.vmerror( "bad package id" );
return 0;
}
return false;
}
@@ -179,8 +172,8 @@ public class PackageLib extends LFunction {
* This function may receive optional options after the module name, where
* each option is a function to be applied over the module.
*/
public static void module(LuaState vm) {
LString modname = vm.checklstring(2);
public static int module(LuaState vm) {
LString modname = vm.checklstring(1);
int n = vm.gettop();
LValue value = LOADED.luaGetTable(vm, modname);
LTable module;
@@ -207,14 +200,14 @@ public class PackageLib extends LFunction {
ci.closure.env = module;
// apply the functions
for ( int i=3; i<=n; i++ ) {
for ( int i=2; i<=n; i++ ) {
vm.pushvalue( i ); /* get option (a function) */
vm.pushlvalue( module ); /* module */
vm.call( 1, 0 );
}
// returns no results
vm.resettop();
return 0;
}
/**
@@ -278,30 +271,29 @@ public class PackageLib extends LFunction {
* If there is any error loading or running the module, or if it cannot find any loader for
* the module, then require signals an error.
*/
public void require( LuaState vm ) {
LString name = vm.checklstring(2);
public int require( LuaState vm ) {
LString name = vm.checklstring(1);
LValue loaded = LOADED.luaGetTable(vm, name);
if ( loaded.toJavaBoolean() ) {
if ( loaded == _SENTINEL )
vm.error("loop or previous error loading module '"+name+"'");
vm.resettop();
vm.pushlvalue( loaded );
return;
return 1;
}
vm.resettop();
/* else must load it; iterate over available loaders */
LValue val = pckg.luaGetTable(vm, _LOADERS);
if ( ! val.isTable() )
vm.error( "'package.loaders' must be a table" );
vm.pushlvalue(val);
LTable tbl = (LTable) val;
Vector v = new Vector();
for ( int i=1; true; i++ ) {
vm.rawgeti(1, i);
if ( vm.isnil(-1) ) {
LValue loader = tbl.get(i);
if ( loader.isNil() ) {
vm.error( "module '"+name+"' not found: "+v );
}
/* call loader with module name as argument */
vm.pushlvalue(loader);
vm.pushlstring(name);
vm.call(1, 1);
if ( vm.isfunction(-1) )
@@ -321,45 +313,45 @@ public class PackageLib extends LFunction {
if ( result == _SENTINEL ) { /* module did not set a value? */
LOADED.luaSetTable(vm, name, result=LBoolean.TRUE ); /* _LOADED[name] = true */
}
vm.resettop();
vm.pushlvalue(result);
return 1;
}
public static void loadlib( LuaState vm ) {
vm.checkstring(2);
vm.resettop();
public static int loadlib( LuaState vm ) {
vm.checkstring(1);
vm.pushnil();
vm.pushstring("dynamic libraries not enabled");
vm.pushstring("absent");
return 3;
}
private void loader_preload( LuaState vm ) {
LString name = vm.tolstring(2);
private int loader_preload( LuaState vm ) {
LString name = vm.tolstring(1);
LValue preload = pckg.luaGetTable(vm, _PRELOAD);
if ( ! preload.isTable() )
vm.error("package.preload '"+name+"' must be a table");
LValue val = preload.luaGetTable(vm, name);
if ( val.isNil() )
vm.pushstring("\n\tno field package.preload['"+name+"']");
vm.resettop();
else
vm.pushlvalue(val);
return 1;
}
private void loader_Lua( LuaState vm ) {
String name = vm.tostring(2);
private int loader_Lua( LuaState vm ) {
String name = vm.tostring(1);
InputStream is = findfile( vm, name, _PATH );
if ( is != null ) {
String filename = vm.tostring(-1);
if ( ! BaseLib.loadis(vm, is, filename) )
loaderror( vm, filename );
}
vm.insert(1);
vm.settop(1);
return 1;
}
private void loader_Java( LuaState vm ) {
String name = vm.tostring(2);
private int loader_Java( LuaState vm ) {
String name = vm.tostring(1);
Class c = null;
LValue v = null;
try {
@@ -371,8 +363,7 @@ public class PackageLib extends LFunction {
} catch ( Exception e ) {
vm.pushstring("\n\tjava load failed on '"+name+"', "+e );
}
vm.insert(1);
vm.settop(1);
return 1;
}
private InputStream findfile(LuaState vm, String name, LString pname) {

View File

@@ -92,58 +92,44 @@ public class StringLib extends LFunction {
return NAMES[id]+"()";
}
public boolean luaStackCall( LuaState vm ) {
public int invoke( LuaState vm ) {
switch ( id ) {
case INSTALL:
install( vm._G );
break;
return 0;
case BYTE:
StringLib.byte_( vm );
break;
return StringLib.byte_( vm );
case CHAR:
StringLib.char_( vm );
break;
return StringLib.char_( vm );
case DUMP:
StringLib.dump( vm );
break;
return StringLib.dump( vm );
case FIND:
StringLib.find( vm );
break;
return StringLib.find( vm );
case FORMAT:
StringLib.format( vm );
break;
return StringLib.format( vm );
case GMATCH:
StringLib.gmatch( vm );
break;
return StringLib.gmatch( vm );
case GSUB:
StringLib.gsub( vm );
break;
return StringLib.gsub( vm );
case LEN:
StringLib.len( vm );
break;
return StringLib.len( vm );
case LOWER:
StringLib.lower( vm );
break;
return StringLib.lower( vm );
case MATCH:
StringLib.match( vm );
break;
return StringLib.match( vm );
case REP:
StringLib.rep( vm );
break;
return StringLib.rep( vm );
case REVERSE:
StringLib.reverse( vm );
break;
return StringLib.reverse( vm );
case SUB:
StringLib.sub( vm );
break;
return StringLib.sub( vm );
case UPPER:
StringLib.upper( vm );
break;
return StringLib.upper( vm );
default:
vm.error( "bad id" );
return 0;
}
return false;
}
/**
@@ -157,22 +143,22 @@ public class StringLib extends LFunction {
*
* @param vm the calling vm
*/
static void byte_( LuaState vm ) {
LString s = vm.checklstring(2);
static int byte_( LuaState vm ) {
LString s = vm.checklstring(1);
int l = s.m_length;
int posi = posrelat( vm.optint(3,1), l );
int pose = posrelat( vm.optint(4,posi), l );
vm.resettop();
int posi = posrelat( vm.optint(2,1), l );
int pose = posrelat( vm.optint(3,posi), l );
int n,i;
if (posi <= 0) posi = 1;
if (pose > l) pose = l;
if (posi > pose) return; /* empty interval; return no values */
if (posi > pose) return 0; /* empty interval; return no values */
n = (int)(pose - posi + 1);
if (posi + n <= pose) /* overflow? */
vm.error("string slice too long");
vm.checkstack(n);
for (i=0; i<n; i++)
vm.pushinteger(s.luaByte(posi+i-1));
return n;
}
/**
@@ -186,16 +172,16 @@ public class StringLib extends LFunction {
*
* @param vm the calling VM
*/
public static void char_( LuaState vm) {
int n = vm.gettop()-1;
public static int char_( LuaState vm) {
int n = vm.gettop();
byte[] bytes = new byte[n];
for ( int i=0, a=2; i<n; i++, a++ ) {
for ( int i=0, a=1; i<n; i++, a++ ) {
int c = vm.checkint(a);
vm.argcheck((c>=0 && c<256), a, "invalid value");
bytes[i] = (byte) c;
}
vm.resettop();
vm.pushlstring( bytes );
return 1;
}
/**
@@ -207,15 +193,16 @@ public class StringLib extends LFunction {
*
* TODO: port dumping code as optional add-on
*/
static void dump( LuaState vm ) {
LFunction f = vm.checkfunction(2);
static int dump( LuaState vm ) {
LFunction f = vm.checkfunction(1);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
DumpState.dump( ((LClosure)f).p, baos, true );
vm.resettop();
vm.pushlstring(baos.toByteArray());
return 1;
} catch (IOException e) {
vm.error( e.getMessage() );
return 0;
}
}
@@ -235,8 +222,8 @@ public class StringLib extends LFunction {
* If the pattern has captures, then in a successful match the captured values
* are also returned, after the two indices.
*/
static void find( LuaState vm ) {
str_find_aux( vm, true );
static int find( LuaState vm ) {
return str_find_aux( vm, true );
}
/**
@@ -262,11 +249,11 @@ public class StringLib extends LFunction {
* This function does not accept string values containing embedded zeros,
* except as arguments to the q option.
*/
static void format( LuaState vm ) {
LString fmt = vm.checklstring( 2 );
static int format( LuaState vm ) {
LString fmt = vm.checklstring( 1 );
final int n = fmt.length();
LBuffer result = new LBuffer(n);
int arg = 2;
int arg = 1;
for ( int i = 0; i < n; ) {
int c = fmt.luaByte( i++ );
@@ -320,8 +307,8 @@ public class StringLib extends LFunction {
}
}
vm.resettop();
vm.pushlstring( result.toLuaString() );
return 1;
}
private static void addquoted(LBuffer buf, LString s) {
@@ -528,11 +515,11 @@ public class StringLib extends LFunction {
* For this function, a '^' at the start of a pattern does not work as an anchor,
* as this would prevent the iteration.
*/
static void gmatch( LuaState vm ) {
LString src = vm.checklstring( 2 );
LString pat = vm.checklstring( 3 );
vm.resettop();
static int gmatch( LuaState vm ) {
LString src = vm.checklstring( 1 );
LString pat = vm.checklstring( 2 );
vm.pushlvalue( new GMatchAux(vm, src, pat) );
return 1;
}
static class GMatchAux extends LFunction {
@@ -544,7 +531,7 @@ public class StringLib extends LFunction {
this.ms = new MatchState(vm, src, pat);
this.soffset = 0;
}
public boolean luaStackCall(LuaState vm) {
public int invoke(LuaState vm) {
vm.resettop();
for ( ; soffset<srclen; soffset++ ) {
ms.reset();
@@ -553,11 +540,11 @@ public class StringLib extends LFunction {
int soff = soffset;
soffset = res;
ms.push_captures( true, soff, res );
return false;
return -1;
}
}
vm.pushnil();
return false;
return 1;
}
}
@@ -607,12 +594,12 @@ public class StringLib extends LFunction {
* x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t)
* --> x="lua-5.1.tar.gz"
*/
static void gsub( LuaState vm ) {
LString src = vm.checklstring(2);
static int gsub( LuaState vm ) {
LString src = vm.checklstring( 1 );
final int srclen = src.length();
LString p = vm.checklstring(3);
LValue repl = vm.topointer( 4 );
int max_s = vm.optint( 5, srclen + 1 );
LString p = vm.checklstring( 2 );
LValue repl = vm.topointer( 3 );
int max_s = vm.optint( 4, srclen + 1 );
final boolean anchor = p.length() > 0 && p.charAt( 0 ) == '^';
LBuffer lbuf = new LBuffer( srclen );
@@ -637,9 +624,9 @@ public class StringLib extends LFunction {
break;
}
lbuf.append( src.substring( soffset, srclen ) );
vm.resettop();
vm.pushlstring( lbuf.toLuaString() );
vm.pushinteger( n );
return 2;
}
/**
@@ -648,10 +635,9 @@ public class StringLib extends LFunction {
* Receives a string and returns its length. The empty string "" has length 0.
* Embedded zeros are counted, so "a\000bc\000" has length 5.
*/
static void len( LuaState vm ) {
int l = vm.checklstring(2).length();
vm.resettop();
vm.pushinteger( l );
static int len( LuaState vm ) {
vm.pushinteger( vm.checklstring(1).length() );
return 1;
}
/**
@@ -661,10 +647,9 @@ public class StringLib extends LFunction {
* changed to lowercase. All other characters are left unchanged.
* The definition of what an uppercase letter is depends on the current locale.
*/
static void lower( LuaState vm ) {
String s = vm.checkstring(2).toLowerCase();
vm.resettop();
vm.pushstring( s );
static int lower( LuaState vm ) {
vm.pushstring( vm.checkstring(1).toLowerCase() );
return 1;
}
/**
@@ -676,8 +661,8 @@ public class StringLib extends LFunction {
* A third, optional numerical argument init specifies where to start the
* search; its default value is 1 and may be negative.
*/
static void match( LuaState vm ) {
str_find_aux( vm, false );
static int match( LuaState vm ) {
return str_find_aux( vm, false );
}
/**
@@ -685,18 +670,16 @@ public class StringLib extends LFunction {
*
* Returns a string that is the concatenation of n copies of the string s.
*/
static void rep( LuaState vm ) {
LString s = vm.checklstring(2);
int n = vm.checkint( 3 );
vm.resettop();
if ( n >= 0 ) {
static int rep( LuaState vm ) {
LString s = vm.checklstring( 1 );
int n = vm.checkint( 2 );
final byte[] bytes = new byte[ s.length() * n ];
int len = s.length();
for ( int offset = 0; offset < bytes.length; offset += len ) {
s.copyInto( 0, bytes, offset, len );
}
vm.pushlstring( bytes );
}
return 1;
}
/**
@@ -704,14 +687,14 @@ public class StringLib extends LFunction {
*
* Returns a string that is the string s reversed.
*/
static void reverse( LuaState vm ) {
LString s = vm.checklstring(2);
static int reverse( LuaState vm ) {
LString s = vm.checklstring(1);
int n = s.length();
byte[] b = new byte[n];
for ( int i=0, j=n-1; i<n; i++, j-- )
b[j] = (byte) s.luaByte(i);
vm.resettop();
vm.pushlstring( b );
return 1;
}
/**
@@ -725,12 +708,12 @@ public class StringLib extends LFunction {
* string.sub(s, -i)
* returns a suffix of s with length i.
*/
static void sub( LuaState vm ) {
final LString s = vm.checklstring(2);
static int sub( LuaState vm ) {
final LString s = vm.checklstring( 1 );
final int l = s.length();
int start = posrelat( vm.checkint( 3 ), l );
int end = posrelat( vm.optint( 4, -1 ), l );
int start = posrelat( vm.checkint( 2 ), l );
int end = posrelat( vm.optint( 3, -1 ), l );
if ( start < 1 )
start = 1;
@@ -744,6 +727,7 @@ public class StringLib extends LFunction {
} else {
vm.pushstring( "" );
}
return 1;
}
/**
@@ -753,19 +737,18 @@ public class StringLib extends LFunction {
* changed to uppercase. All other characters are left unchanged.
* The definition of what a lowercase letter is depends on the current locale.
*/
static void upper( LuaState vm ) {
String s = vm.checkstring(2).toUpperCase();
vm.resettop();
vm.pushstring(s);
static int upper( LuaState vm ) {
vm.pushstring(vm.checkstring(1).toUpperCase());
return 1;
}
/**
* This utility method implements both string.find and string.match.
*/
static void str_find_aux( LuaState vm, boolean find ) {
LString s = vm.checklstring(2);
LString pat = vm.checklstring(3);
int init = vm.optint( 4 , 1 );
static int str_find_aux( LuaState vm, boolean find ) {
LString s = vm.checklstring( 1 );
LString pat = vm.checklstring( 2 );
int init = vm.optint( 3, 1 );
if ( init > 0 ) {
init = Math.min( init - 1, s.length() );
@@ -774,14 +757,13 @@ public class StringLib extends LFunction {
}
boolean fastMatch = find && ( vm.toboolean( 5 ) || pat.indexOfAny( SPECIALS ) == -1 );
vm.resettop();
if ( fastMatch ) {
int result = s.indexOf( pat, init );
if ( result != -1 ) {
vm.pushinteger( result + 1 );
vm.pushinteger( result + pat.length() );
return;
return 2;
}
} else {
MatchState ms = new MatchState( vm, s, pat );
@@ -794,6 +776,7 @@ public class StringLib extends LFunction {
}
int soff = init;
vm.resettop();
do {
int res;
ms.reset();
@@ -805,11 +788,12 @@ public class StringLib extends LFunction {
} else {
ms.push_captures( true, soff, res );
}
return;
return -1;
}
} while ( soff++ < s.length() && !anchor );
}
vm.pushnil();
return 1;
}
private static int posrelat( int pos, int len ) {

View File

@@ -79,14 +79,14 @@ public class TableLib extends LFunction {
return NAMES[id]+"()";
}
public boolean luaStackCall( LuaState vm ) {
public int invoke( LuaState vm ) {
switch ( id ) {
/* Load the table library dynamically
*/
case INSTALL:
install(vm._G);
break;
return 0;
/* table.concat (table [, sep [, i [, j]]])
@@ -96,25 +96,24 @@ public class TableLib extends LFunction {
* If i is greater than j, returns the empty string.
*/
case CONCAT: {
int n = vm.gettop();
LTable table = vm.checktable(2);
LString sep = vm.optlstring(3,null);
int i = vm.optint(4,1);
int j = vm.optint(5,-1);
// int n = vm.gettop();
LTable table = vm.checktable(1);
LString sep = vm.optlstring(2,null);
int i = vm.optint(3,1);
int j = vm.optint(4,-1);
if ( j == -1 )
j = table.luaLength();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for ( int k=i; k<=j; k++ ) {
LValue v = table.get(k);
if ( ! v.isString() )
vm.argerror(2, "table contains non-strings");
vm.argerror(1, "table contains non-strings");
v.luaConcatTo(baos);
if ( k<j && sep!=null )
sep.luaConcatTo( baos );
}
vm.resettop();
vm.pushlstring( baos.toByteArray() );
break;
return 1;
}
/* table.getn (table)
@@ -124,12 +123,10 @@ public class TableLib extends LFunction {
case FOREACH:
case FOREACHI:
{
LTable table = vm.checktable(2);
LFunction function = vm.checkfunction(3);
LValue result = table.foreach( vm, function, id==FOREACHI );
vm.resettop();
vm.pushlvalue( result );
break;
LTable table = vm.checktable(1);
LFunction function = vm.checkfunction(2);
vm.pushlvalue( table.foreach( vm, function, id==FOREACHI ) );
return 1;
}
/* table.getn (table)
@@ -137,10 +134,9 @@ public class TableLib extends LFunction {
* Get length of table t.
*/
case GETN: {
LTable table = vm.checktable(2);
vm.resettop();
LTable table = vm.checktable(1);
vm.pushinteger(table.luaLength());
break;
return 1;
}
/* table.insert (table, [pos,] value)
@@ -150,20 +146,19 @@ public class TableLib extends LFunction {
* table.insert(t,x) inserts x at the end of table t.
*/
case INSERT: {
LTable table = vm.checktable(2);
LTable table = vm.checktable(1);
int pos = 0;
switch ( vm.gettop() ) {
case 3:
case 2:
break;
case 4:
pos = vm.checkint(3);
case 3:
pos = vm.checkint(2);
break;
default:
vm.error( "wrong number of arguments to 'insert'" );
}
table.luaInsertPos( pos, vm.topointer(-1) );
vm.resettop();
break;
return 0;
}
/* table.maxn (table)
@@ -172,10 +167,9 @@ public class TableLib extends LFunction {
* indices. (To do its job this function does a linear traversal of the whole table.)
*/
case MAXN: {
LTable table = vm.checktable(2);
vm.resettop();
LTable table = vm.checktable(1);
vm.pushlvalue( table.luaMaxN() );
break;
return 1;
}
/* table.remove (table [, pos])
@@ -185,14 +179,11 @@ public class TableLib extends LFunction {
* so that a call table.remove(t) removes the last element of table t.
*/
case REMOVE: {
int n = vm.gettop();
LTable table = vm.checktable(2);
int pos = vm.optint(3,0);
vm.resettop();
LValue removed = table.luaRemovePos( pos );
if ( removed != LNil.NIL )
vm.pushlvalue( removed );
break;
LTable table = vm.checktable(1);
int pos = vm.optint(2,0);
LValue v = table.luaRemovePos( pos );
vm.pushlvalue( v );
return v.isNil()? 0: 1;
}
/* table.sort (table [, comp])
@@ -205,16 +196,15 @@ public class TableLib extends LFunction {
* The sort algorithm is not stable; that is, elements considered equal by the given order may have their relative positions changed by the sort.
*/
case SORT: {
LTable table = vm.checktable(2);
LValue compare = (vm.isnoneornil(3)? (LValue) LNil.NIL: (LValue) vm.checkfunction(3));
LTable table = vm.checktable(1);
LValue compare = (vm.isnoneornil(2)? (LValue) LNil.NIL: (LValue) vm.checkfunction(2));
table.luaSort( vm, compare );
vm.resettop();
break;
return 0;
}
default:
LuaState.vmerror( "bad table id" );
return 0;
}
return false;
}
}

View File

@@ -84,7 +84,7 @@ public class LThread extends LValue implements Runnable {
}
}
public boolean yield() {
public void yield() {
synchronized ( this ) {
if ( status != STATUS_RUNNING )
vm.error(this+" not running");
@@ -99,7 +99,6 @@ public class LThread extends LValue implements Runnable {
vm.error(this+" "+e);
}
}
return false;
}
}
@@ -157,7 +156,7 @@ public class LThread extends LValue implements Runnable {
vm.resettop();
if ( this.vm.cc >= 0 ) {
vm.pushboolean(status != STATUS_DEAD);
this.vm.xmove(vm, this.vm.gettop() - 1);
this.vm.xmove(vm, this.vm.gettop());
} else {
vm.pushboolean(true);
this.vm.base = 0;

View File

@@ -247,16 +247,12 @@ public class LuaState extends Lua {
* @param javaFunction
*/
public void invokeJavaFunction(LFunction javaFunction) {
int resultbase = base;
int resultsneeded = nresults;
++base;
int nactual = javaFunction.invoke(this);
debugAssert(nactual>=0);
debugAssert(top-nactual>=base);
System.arraycopy(stack, top-nactual, stack, base=resultbase, nactual);
settop( nactual );
if ( resultsneeded >= 0 )
settop( resultsneeded );
if (nactual < 0)
nactual = top - base;
System.arraycopy(stack, top-nactual, stack, --base, nactual);
luaV_settop_fillabove( base+nactual );
}
// ================== error processing =================
@@ -1969,7 +1965,7 @@ public class LuaState extends Lua {
* @param extramsg String to include in error message
*/
public void argerror(int narg, String extramsg) {
error("bad argument #" + (narg - 1) + " (" + extramsg + ")");
error("bad argument #" + (narg) + " (" + extramsg + ")");
}
/**