From 4bdd4a6ea232d0895d54402638134dfba885f09f Mon Sep 17 00:00:00 2001 From: James Roseborough Date: Wed, 25 Mar 2009 14:43:24 +0000 Subject: [PATCH] Enhance debug tests, fix debug lib off-by-one erros. --- src/core/org/luaj/lib/DebugLib.java | 38 ++++++++------ src/j2se/lua.java | 3 ++ .../java/org/luaj/vm/CompatibiltyTest.java | 4 ++ .../java/org/luaj/vm/ScriptDrivenTest.java | 4 ++ src/test/res/debuglib.lua | 50 ++++++++++++++++++- 5 files changed, 83 insertions(+), 16 deletions(-) diff --git a/src/core/org/luaj/lib/DebugLib.java b/src/core/org/luaj/lib/DebugLib.java index ca945683..3dc793a4 100644 --- a/src/core/org/luaj/lib/DebugLib.java +++ b/src/core/org/luaj/lib/DebugLib.java @@ -36,6 +36,7 @@ import org.luaj.vm.LuaState; public class DebugLib extends LFunction { private static final String[] NAMES = { + "debuglib", "debug", "getfenv", "gethook", @@ -70,14 +71,18 @@ public class DebugLib extends LFunction { public static void install( LuaState vm ) { LTable debug = new LTable(); - for (int i = 0; i < NAMES.length; i++) - debug.put(NAMES[i], new DebugLib(i + 1)); + for (int i = 1; i < NAMES.length; i++) + debug.put(NAMES[i], new DebugLib(i)); vm._G.put("debug", debug); PackageLib.setIsLoaded("debug", debug); } private final int id; + public DebugLib() { + this.id = INSTALL; + } + private DebugLib( int id ) { this.id = id; } @@ -177,6 +182,7 @@ public class DebugLib extends LFunction { private void getfenv(LuaState vm) { LValue object = vm.topointer(2); LValue env = object.luaGetEnv(null); + vm.resettop(); vm.pushlvalue(env!=null? env: LNil.NIL); } @@ -184,6 +190,7 @@ public class DebugLib extends LFunction { LValue object = vm.topointer(2); LTable table = vm.checktable(3); object.luaSetEnv(table); + vm.settop(1); } private void getinfo(LuaState vm) { @@ -263,11 +270,11 @@ public class DebugLib extends LFunction { CallInfo ci = getcallinfo(vm, threadVm, level); LValue value = LNil.NIL; LValue name = LNil.NIL; - if ( local >= 0 && local < ci.top-ci.base ) { - value = threadVm.stack[ ci.base + local ]; - LocVars[] vars = ci.closure.p.locvars; - if ( vars != null && local >= 0 && local < vars.length ) - name = vars[local].varname; + LocVars[] vars = ci.closure.p.locvars; + if ( local > 0 && local <= ci.top-ci.base ) { + value = threadVm.stack[ ci.base + local - 1 ]; + if ( vars != null && local > 0 && local <= vars.length ) + name = vars[local-1].varname; } vm.resettop(); vm.pushlvalue( name ); @@ -276,7 +283,7 @@ public class DebugLib extends LFunction { private void setlocal(LuaState vm) { LuaState threadVm = vm; - if ( vm.gettop() >= 4 ) { + if ( vm.gettop() >= 5 ) { threadVm = vm.checkthread(2).vm; vm.remove(2); } @@ -285,20 +292,21 @@ public class DebugLib extends LFunction { LValue value = vm.topointer(4); CallInfo ci = getcallinfo(vm, threadVm, level); LValue name = LNil.NIL; - if ( local >= 0 && local < ci.top-ci.base ) { - threadVm.stack[ ci.base + local ] = value; - LocVars[] vars = ci.closure.p.locvars; - if ( vars != null && local >= 0 && local < vars.length ) - name = vars[local].varname; + LocVars[] vars = ci.closure.p.locvars; + if ( local > 0 && local <= ci.top-ci.base ) { + threadVm.stack[ ci.base + local - 1 ] = value; + if ( vars != null && local > 0 && local <= vars.length ) + name = vars[local-1].varname; } vm.resettop(); vm.pushlvalue( name ); } private CallInfo getcallinfo(LuaState vm, LuaState threadVm, int level) { - if ( level <= 0 || level > threadVm.cc ) + --level ; // level 0 is the debug function itself + if ( level < 0 || level > threadVm.cc ) vm.error("level out of range"); - int cc = threadVm.cc-(level-1); + int cc = threadVm.cc-level; return threadVm.calls[cc]; } diff --git a/src/j2se/lua.java b/src/j2se/lua.java index 6a184f8e..2f8ff0c4 100644 --- a/src/j2se/lua.java +++ b/src/j2se/lua.java @@ -121,6 +121,9 @@ public class lua { break; } else { switch ( args[i].charAt(1) ) { + case 'l': + ++i; + break; case 'e': ++i; processScript( vm, new ByteArrayInputStream(args[i].getBytes()), args[i], null, 0 ); diff --git a/src/test/java/org/luaj/vm/CompatibiltyTest.java b/src/test/java/org/luaj/vm/CompatibiltyTest.java index 69d1672c..d63f1570 100644 --- a/src/test/java/org/luaj/vm/CompatibiltyTest.java +++ b/src/test/java/org/luaj/vm/CompatibiltyTest.java @@ -76,6 +76,10 @@ public class CompatibiltyTest extends ScriptDrivenTest { runTest("compare"); } + public void testDebugLib() throws IOException, InterruptedException { + runTest("debuglib"); + } + public void testErrors() throws IOException, InterruptedException { runTest("errors"); } diff --git a/src/test/java/org/luaj/vm/ScriptDrivenTest.java b/src/test/java/org/luaj/vm/ScriptDrivenTest.java index 4d195cbb..316722f4 100644 --- a/src/test/java/org/luaj/vm/ScriptDrivenTest.java +++ b/src/test/java/org/luaj/vm/ScriptDrivenTest.java @@ -11,6 +11,7 @@ import junit.framework.TestCase; import org.luaj.compiler.LuaC; import org.luaj.lib.BaseLib; +import org.luaj.lib.DebugLib; import org.luaj.platform.J2sePlatform; abstract @@ -35,6 +36,9 @@ public class ScriptDrivenTest extends TestCase { // install the compiler LuaC.install(); + // install debug lib + DebugLib.install( state ); + // load the file LPrototype p = loadScript(state, testName); p.source = LString.valueOf("stdin"); diff --git a/src/test/res/debuglib.lua b/src/test/res/debuglib.lua index da7727d3..239c5b63 100644 --- a/src/test/res/debuglib.lua +++ b/src/test/res/debuglib.lua @@ -1,7 +1,54 @@ -local print = print +local print,tostring,_G = print,tostring,_G +local e,f,g,h,s print( 'has debug', debug~=nil ) +-- debug.getfenv, debug.setfenv +print( '----- debug.getfenv, debug.setfenv' ) +f = function(a) + return 'f:'..tostring(a)..'|'..tostring(b) +end +s,e,g = pcall( debug.getfenv, f ) +print( s, type(e), type(g), (e==G), pcall( f, 'abc' ) ) +s,e,g = pcall( debug.setfenv, f, {b='def'} ) +print( s, type(e), type(g), (e==G), pcall( f, 'abc' ) ) +s,e,g = pcall( debug.getfenv, f ) +print( s, type(e), type(g), (e==G), pcall( f, 'abc' ) ) + + +print( '----- debug.getlocal, debug.setlocal' ) +h = function(v,i,n) + s = 'h-'..v..'-'..i + local x = debug.getlocal(v,i) + local y = debug.setlocal(v,i,n) + return s..' -> '..v..'-'..i..' '.. + 'old='..tostring(x)..'('..tostring(y)..')'..' '.. + 'new='..tostring(n) +end +g = function(...) + local p,q,r=7,8,9 + local t = h(...) + local b = table.concat({...},',') + return t..'\tg locals='..p..','..q..','..r..' tbl={'..b..'}' +end +f = function(a,b,c) + local d,e,f = 4,5,6 + local t = g(a,b,c) + return t..'\tf locals='..','..a..','..b..','..c..','..d..','..e..','..f +end +for lvl=1,3 do + for lcl=0,7 do + print( pcall( f, lvl, lcl, '#' ) ) + end +end + +--[[ +local f = function(a) + return 'f:'..tostring(a)..'|'..tostring(b) +end +local s,e + + local printinfo = function(...) for i,a in ipairs(arg) do if type(a) == 'table' then @@ -38,3 +85,4 @@ print( 'e,f,g', e, type(f), type(g) ) printinfo( 'debug.getinfo(f,"Sl")', pcall(debug.getinfo, f, "Sl") ) printinfo( 'debug.getinfo(g,"Sl")', pcall(debug.getinfo, g, "Sl") ) printinfo( 'debug.getinfo(test,"Sl")', pcall(debug.getinfo, test, "Sl") ) +--]] \ No newline at end of file