Fixes to debug.sethook, debug.gethook, and debug.getinfo functions.

This commit is contained in:
James Roseborough
2009-03-26 05:13:06 +00:00
parent 512304475e
commit d236c31650
3 changed files with 142 additions and 61 deletions

View File

@@ -168,12 +168,12 @@ public class DebugLib extends LFunction {
threadVm = vm.checkthread(2).vm;
vm.remove(2);
}
LFunction func = vm.checkfunction(2);
LString str = vm.checklstring(3);
LFunction func = vm.isnoneornil(2)? null: vm.checkfunction(2);
String str = vm.optstring(3,"");
int count = vm.optint(4,0);
int mask = 0;
for ( int i=0; i<str.m_length; i++ )
switch ( str.m_bytes[str.m_offset+i] ) {
for ( int i=0; i<str.length(); i++ )
switch ( str.charAt(i) ) {
case 'c': mask |= LuaState.LUA_MASKCALL; break;
case 'l': mask |= LuaState.LUA_MASKLINE; break;
case 'r': mask |= LuaState.LUA_MASKRET; break;
@@ -201,14 +201,11 @@ public class DebugLib extends LFunction {
CallInfo ci = null;
LFunction func = null;
LClosure closure = null;
String what = "";
if ( vm.gettop() >= 4 ) {
threadVm = vm.checkthread(2).vm;
vm.remove(2);
}
if ( vm.gettop() >= 3 ) {
what = vm.tostring(3);
}
String what = vm.optstring(3, "nSluf");
if ( vm.isnumber(2) ) {
ci = this.getcallinfo(vm, threadVm, vm.tointeger(2));
closure = ci.closure;
@@ -223,20 +220,20 @@ public class DebugLib extends LFunction {
for (int i = 0, n = what.length(); i < n; i++) {
switch (what.charAt(i)) {
case 'S': {
info.put("source", (closure!=null? closure.p.source: new LString("@?")));
info.put("short_src", (closure!=null? closure.p.source.substring(1, closure.p.source.m_length-1): new LString("?")));
String s = (closure!=null? closure.p.source.toJavaString(): "=?");
info.put("source", new LString(s.replace('@','=')));
info.put("short_src", new LString(s.substring(1)));
info.put("linedefined", (closure!=null? closure.p.linedefined: 0));
info.put("lastlinedefined", (closure!=null? closure.p.lastlinedefined: 0));
info.put("what", new LString(what));
info.put("what", new LString("Lua"));
break;
}
case 'l': {
info.put( "currentline", (ci!=null? ci.pc: 0) );
info.put( "currentline", currentline(threadVm, ci, func) );
break;
}
case 'u': {
info.put("nups", (closure!=null? closure.p.nups: 0));
info.put("what", new LString(what));
break;
}
case 'n': {
@@ -246,22 +243,40 @@ public class DebugLib extends LFunction {
break;
}
case 'f': {
if ( func != null )
info.put( "func", func );
info.put( "func", closure );
break;
}
case 'L': {
LTable lines = new LTable();
info.put("activelines", lines);
if ( closure != null )
for ( int j=0, k=1; j<closure.p.lineinfo.length; j++, k++ )
lines.put(k, LInteger.valueOf(closure.p.lineinfo[j]));
for ( int j=threadVm.cc, k=1; j>=0; --j )
if ( threadVm.calls[j].closure == func ) {
int line = threadVm.debugGetLineNumber(ci);
if ( line >= 0 )
lines.put(k++, LInteger.valueOf(line));
}
break;
}
}
}
}
private int currentline(LuaState vm, CallInfo ci, LFunction func) {
if ( ci == null ) {
ci = findcallinfo(vm, func);
if ( ci == null )
return -1;
}
return vm.debugGetLineNumber(ci);
}
private CallInfo findcallinfo(LuaState vm, LFunction func) {
for ( int i=vm.cc; i>=0; --i )
if ( vm.calls[i].closure == func )
return vm.calls[i];
return null;
}
private LString getlocalname (LPrototype f, int local_number, int pc) {
int i;
for (i = 0; i<f.locvars.length && f.locvars[i].startpc <= pc; i++) {
@@ -423,7 +438,6 @@ public class DebugLib extends LFunction {
LuaState threadVm = vm;
int level = 1;
String message = "";
StringBuffer sb = new StringBuffer();
if ( vm.gettop() >= 4 ) {
threadVm = vm.checkthread(2).vm;
vm.remove(2);
@@ -432,8 +446,10 @@ public class DebugLib extends LFunction {
level = vm.optint(3,1);
if ( vm.gettop() >= 2 )
message = vm.tostring(2)+"\n";
message += threadVm.getStackTrace(level);
String trace = threadVm.getStackTrace(level-1);
if ( trace.endsWith("\n") )
trace = trace.substring(0,trace.length()-1);
vm.resettop();
vm.pushstring(sb.toString());
vm.pushstring(message+trace);
}
}

View File

@@ -110,7 +110,7 @@ public class LuaState extends Lua {
private int hookcount;
private LFunction hookfunc;
private int hookincr;
private int hookline;
private int hookline,hookcc;
protected void debugAssert(boolean b) {}
@@ -714,7 +714,7 @@ public class LuaState extends Lua {
// call hook
if ( hooksenabled ) {
debugCallHooks( ci.pc-1 );
debugCallHooks( );
}
// make or set up the call
@@ -737,7 +737,7 @@ public class LuaState extends Lua {
case LuaState.OP_TAILCALL: {
// return hook
if ( hooksenabled ) {
debugTailReturnHooks( ci.pc-1 );
debugTailReturnHooks( );
}
// close up values
@@ -785,7 +785,7 @@ public class LuaState extends Lua {
case LuaState.OP_RETURN: {
// return hook
if ( hooksenabled ) {
debugReturnHooks( ci.pc-1 );
debugReturnHooks( );
}
// close up values
@@ -2414,8 +2414,9 @@ public class LuaState extends Lua {
private void debugBytecodeHooks(int pc) {
if ( hookfunc != null && (hookmask & LUA_MASKLINE) != 0 ) {
int line = debugGetLineNumber(calls[cc]);
if ( line != hookline ) {
if ( (line != hookline || cc != hookcc) && line >= 0 ) {
hookline = line;
hookcc = cc;
debugCallHook(LUA_HOOKLINE, line);
}
if (hookcount != 0) {
@@ -2427,52 +2428,56 @@ public class LuaState extends Lua {
}
}
private void debugCallHooks(int pc) {
private void debugCallHooks() {
if ( hookfunc != null && ((hookmask & LUA_MASKCALL) != 0) ) {
debugCallHook(LUA_HOOKCALL, debugGetLineNumber(calls[cc]));
hookline = -1;
}
}
private void debugReturnHooks(int pc) {
private void debugReturnHooks() {
if ( hookfunc != null && ((hookmask & LUA_MASKRET) != 0) ) {
debugCallHook(LUA_HOOKRET, debugGetLineNumber(calls[cc]));
hookline = -1;
}
}
private void debugTailReturnHooks(int pc) {
private void debugTailReturnHooks() {
if ( hookfunc != null && ((hookmask & LUA_MASKRET) != 0) ) {
debugCallHook(LUA_HOOKTAILRET, debugGetLineNumber(calls[cc]));
hookline = -1;
}
}
private int debugGetLineNumber(CallInfo ci) {
int[] lineNumbers = ci.closure.p.lineinfo;
int pc = getCurrentPc(ci);
int line = (lineNumbers != null && lineNumbers.length > pc ?
lineNumbers[pc] :
-1);
return line;
public int debugGetLineNumber(CallInfo ci) {
int[] li = ci.closure.p.lineinfo;
int pc = ci.pc - 1;
if ( li != null && pc >= 0 && pc < li.length )
return li[pc];
return -1;
}
private void debugCallHook(int mask, int newline) {
private void debugCallHook(int mask, int line) {
int prevmask = hookmask;
int oldtop = top;
LValue lineval = LNil.NIL;
try {
if ( cc >= 0 )
top = base + this.calls[cc].closure.p.maxstacksize;
hookmask = 0;
this.pushfunction(hookfunc);
switch ( mask ) {
default: this.pushstring("line"); break;
case LUA_HOOKCOUNT: this.pushstring("count"); break;
case LUA_HOOKCALL: this.pushstring("call"); break;
case LUA_HOOKRET: this.pushstring("return"); break;
case LUA_HOOKTAILRET: this.pushstring("tail return"); break;
case LUA_HOOKTAILRET: this.pushstring("return"); break;
default:
lineval = LInteger.valueOf(line);
this.pushstring("line");
break;
}
this.pushinteger(newline);
this.pushlvalue(lineval);
this.pcall(2, 0, 0);
} finally {
hookmask = prevmask;
top = oldtop;
}
}
}

View File

@@ -117,29 +117,32 @@ print( pcall( debug.getmetatable, 1 ) )
-- print( pcall( debug.setmetatable, 1, {} ) )
-- print( pcall( debug.setmetatable, 1, nil ) )
--[[
local f = function(a)
return 'f:'..tostring(a)..'|'..tostring(b)
print( '----- debug.getinfo' )
local printfield = function(tbl, field)
local x = tbl[field]
if x == nil then return end
local typ = type(x)
if typ=='table' then
x = '{'..table.concat(x,',')..'}'
elseif typ=='function' then
x = typ
end
print( ' '..field..': '..tostring(x) )
end
local s,e
local fields = { 'source', 'short_src', 'what',
'currentline', 'linedefined', 'lastlinedefined',
'nups', 'func', 'activelines' }
local printinfo = function(...)
for i,a in ipairs(arg) do
if type(a) == 'table' then
print( ' source: '..tostring(a.source) )
print( ' short_src: '..tostring(a.short_src) )
print( ' what: '..tostring(a.what) )
print( ' currentline: '..tostring(a.currentline) )
print( ' linedefined: '..tostring(a.linedefined) )
print( ' lastlinedefined: '..tostring(a.lastlinedefined) )
for j,field in ipairs(fields) do
printfield( a, field)
end
else
print( tostring(a) )
end
end
end
function test()
local x = 5
function f()
@@ -148,6 +151,20 @@ function test()
end
function g()
x = x - 1
print( '---' )
printinfo( 'debug.getinfo(1)', debug.getinfo(1) )
printinfo( 'debug.getinfo(1,"l")', debug.getinfo(1, "l") )
printinfo( 'debug.getinfo(1,"fL")', debug.getinfo(1, "fL") )
printinfo( 'debug.getinfo(2)', debug.getinfo(2) )
printinfo( 'debug.getinfo(2,"l")', debug.getinfo(2, "l") )
printinfo( 'debug.getinfo(2,"fL")', debug.getinfo(2, "fL") )
--[[
for i=1,3 do
printinfo( 'debug.traceback("msg")', debug.traceback('msg') )
printinfo( 'debug.traceback("another",'..i..')', debug.traceback('another',i) )
end
--]]
print( '---' )
return x
end
print(f())
@@ -155,10 +172,53 @@ function test()
return f, g
end
local options = "nSlufL"
local e,f,g = pcall( test )
print( 'e,f,g', e, type(f), type(g) )
printinfo( 'debug.getinfo(f)', pcall(debug.getinfo, f) )
printinfo( 'debug.getinfo(f,"'..options..'")', pcall(debug.getinfo, f, options) )
for j=1,6 do
local opts = options:sub(j,j)
printinfo( 'debug.getinfo(f,"'..opts..'")', pcall(debug.getinfo, f, opts) )
end
printinfo( 'debug.getinfo(g)', pcall(debug.getinfo, g) )
printinfo( 'debug.getinfo(test)', pcall(debug.getinfo, test) )
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") )
--]]
print( '----- debug.sethook, debug.gethook' )
f = function(x)
g = function(y)
return math.min(x,h)
end
local a = g(x)
return a + a
end
local hook = function(...)
print( ' ... in hook', ... )
end
local tryfunc = function(hook,mask,func,arg)
local x,f,h,m
pcall( function()
debug.sethook(hook,mask)
x = func(arg)
f,h,m = debug.gethook()
end )
debug.sethook()
return x,f,h,m
end
local tryhooks = function(mask)
local s1,a1,b1,c1,d1 = pcall( tryfunc, hook, mask, f, 333 )
print( 'hook = '..mask..' -> '..
'result='..tostring(s1)..','..tostring(a1)..','..
type(b1)..','..type(c1)..','..
tostring(b1==f)..','..tostring(c1==hook)..','..
tostring(d1)..' ' )
end
--[[
tryhooks("c")
tryhooks("r")
tryhooks("l")
tryhooks("crl")
--]]