diff --git a/src/debug/org/luaj/debug/DebugStackState.java b/src/debug/org/luaj/debug/DebugStackState.java index f9c9f310..8550b40d 100644 --- a/src/debug/org/luaj/debug/DebugStackState.java +++ b/src/debug/org/luaj/debug/DebugStackState.java @@ -40,7 +40,7 @@ import org.luaj.debug.request.DebugRequestType; import org.luaj.debug.response.DebugResponse; import org.luaj.debug.response.DebugResponseCallgraph; import org.luaj.debug.response.DebugResponseSimple; -import org.luaj.debug.response.DebugResponseStack; +import org.luaj.debug.response.DebugResponseVariables; import org.luaj.vm.CallInfo; import org.luaj.vm.LClosure; import org.luaj.vm.LTable; @@ -338,7 +338,9 @@ public class DebugStackState extends LuaState implements DebugRequestListener { } else if (DebugRequestType.stack == requestType) { DebugRequestStack stackRequest = (DebugRequestStack) request; int index = stackRequest.getIndex(); - return new DebugResponseStack(getStack(index)); + return new DebugResponseVariables(getStack(index)); + } else if (DebugRequestType.global == requestType) { + return new DebugResponseVariables(getGlobals()); } else if (DebugRequestType.stepInto == requestType) { DebugEvent event = new DebugEvent( DebugEventType.resumedOnSteppingInto); @@ -485,8 +487,45 @@ public class DebugStackState extends LuaState implements DebugRequestListener { Vector variables = new Vector(); Hashtable variablesSeen = new Hashtable(); - addVariables(variables, variablesSeen, index); + LPrototype p = calls[index].closure.p; + for (int i = index; i >= 0; i--) { + if (i == index || isInScope(p, calls[i])) { + addVariables(variables, variablesSeen, i); + } + } + Variable[] result = new Variable[variables.size()]; + for (int i = 0; i < variables.size(); i++) { + result[i] = (Variable) variables.elementAt(i); + } + return result; + } + + protected boolean isInScope(LPrototype p, CallInfo ci) { + LPrototype[] enclosingProtos = ci.closure.p.p; + boolean bFound = false; + for (int i = 0; enclosingProtos!= null && i < enclosingProtos.length; i++) { + if (enclosingProtos[i] == p) { + bFound = true; + break; + } + } + + return bFound; + } + + /** + * Returns the visible globals to the current VM. + * @return the visible globals. + */ + public Variable[] getGlobals() { + Vector variables = new Vector(); + variables.addElement( + new TableVariable(0, + "*Globals*", + Lua.LUA_TTABLE, + (LTable) _G)); + Variable[] result = new Variable[variables.size()]; for (int i = 0; i < variables.size(); i++) { result[i] = (Variable) variables.elementAt(i); diff --git a/src/debug/org/luaj/debug/SerializationHelper.java b/src/debug/org/luaj/debug/SerializationHelper.java index 1608a773..18574276 100644 --- a/src/debug/org/luaj/debug/SerializationHelper.java +++ b/src/debug/org/luaj/debug/SerializationHelper.java @@ -16,161 +16,164 @@ import org.luaj.debug.request.DebugRequestStack; import org.luaj.debug.request.DebugRequestType; import org.luaj.debug.response.DebugResponseCallgraph; import org.luaj.debug.response.DebugResponseSimple; -import org.luaj.debug.response.DebugResponseStack; - +import org.luaj.debug.response.DebugResponseVariables; public class SerializationHelper { - public static byte[] serialize(Serializable object) throws IOException { - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - DataOutputStream dout = new DataOutputStream(bout); - - serialize(object, dout); - - byte[] data = bout.toByteArray(); - - bout.close(); - dout.close(); - - return data; - } - - public static Serializable deserialize(byte[] data) throws IOException { - ByteArrayInputStream bin = new ByteArrayInputStream(data); - DataInputStream din = new DataInputStream(bin); - - Serializable object = deserialize(din); - - bin.close(); - din.close(); - - return object; + public static byte[] serialize(Serializable object) throws IOException { + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + DataOutputStream dout = new DataOutputStream(bout); + + serialize(object, dout); + + byte[] data = bout.toByteArray(); + + bout.close(); + dout.close(); + + return data; + } + + public static Serializable deserialize(byte[] data) throws IOException { + ByteArrayInputStream bin = new ByteArrayInputStream(data); + DataInputStream din = new DataInputStream(bin); + + Serializable object = deserialize(din); + + bin.close(); + din.close(); + + return object; } - static final int SERIAL_TYPE_NullableString = 0; static final int SERIAL_TYPE_TableVariable = 1; static final int SERIAL_TYPE_Variable = 2; static final int SERIAL_TYPE_DebugResponseCallgraph = 3; - static final int SERIAL_TYPE_DebugResponseStack = 4; - static final int SERIAL_TYPE_DebugResponseSimple = 5; - static final int SERIAL_TYPE_StackFrame = 6; - static final int SERIAL_TYPE_DebugRequestType = 7; - static final int SERIAL_TYPE_DebugRequest = 8; - static final int SERIAL_TYPE_DebugRequestStack = 9; - static final int SERIAL_TYPE_DebugRequestLineBreakpointToggle = 10; - static final int SERIAL_TYPE_DebugEventType = 11; - static final int SERIAL_TYPE_DebugEvent = 12; - static final int SERIAL_TYPE_DebugEventBreakpoint = 13; - static final int SERIAL_TYPE_DebugEventError = 14; - - public static void serialize(Serializable object, DataOutputStream dout) - throws IOException { - if (object instanceof NullableString) { - dout.writeInt(SERIAL_TYPE_NullableString); - NullableString.serialize(dout, (NullableString)object); - } else if (object instanceof TableVariable) { - dout.writeInt(SERIAL_TYPE_TableVariable); - TableVariable.serialize(dout, (TableVariable)object); - } else if (object instanceof Variable) { - dout.writeInt(SERIAL_TYPE_Variable); - Variable.serialize(dout, (Variable)object); - } else if (object instanceof StackFrame) { - dout.writeInt(SERIAL_TYPE_StackFrame); - StackFrame.serialize(dout, (StackFrame)object); - } else if (object instanceof DebugResponseSimple) { - dout.writeInt(SERIAL_TYPE_DebugResponseSimple); - DebugResponseSimple.serialize(dout, (DebugResponseSimple)object); - } else if (object instanceof DebugResponseStack) { - dout.writeInt(SERIAL_TYPE_DebugResponseStack); - DebugResponseStack.serialize(dout, (DebugResponseStack)object); - } else if (object instanceof DebugResponseCallgraph) { - dout.writeInt(SERIAL_TYPE_DebugResponseCallgraph); - DebugResponseCallgraph.serialize(dout, (DebugResponseCallgraph)object); - } else if (object instanceof DebugRequestType) { - dout.writeInt(SERIAL_TYPE_DebugRequestType); - DebugRequestType.serialize(dout, (DebugRequestType)object); - } else if (object instanceof DebugRequestStack) { - dout.writeInt(SERIAL_TYPE_DebugRequestStack); - DebugRequestStack.serialize(dout, (DebugRequestStack)object); - } else if (object instanceof DebugRequestLineBreakpointToggle) { - dout.writeInt(SERIAL_TYPE_DebugRequestLineBreakpointToggle); - DebugRequestLineBreakpointToggle.serialize(dout, (DebugRequestLineBreakpointToggle)object); - } else if (object instanceof DebugRequest) { - dout.writeInt(SERIAL_TYPE_DebugRequest); - DebugRequest.serialize(dout, (DebugRequest)object); - } else if (object instanceof DebugEventType) { - dout.writeInt(SERIAL_TYPE_DebugEventType); - DebugEventType.serialize(dout, (DebugEventType)object); - } else if (object instanceof DebugEventBreakpoint) { - dout.writeInt(SERIAL_TYPE_DebugEventBreakpoint); - DebugEventBreakpoint.serialize(dout, (DebugEventBreakpoint)object); - } else if (object instanceof DebugEventError) { - dout.writeInt(SERIAL_TYPE_DebugEventError); - DebugEventError.serialize(dout, (DebugEventError)object); - } else if (object instanceof DebugEvent) { - dout.writeInt(SERIAL_TYPE_DebugEvent); - DebugEvent.serialize(dout, (DebugEvent)object); - } else { - // catch the errors: forgot to implement serialization/deserialization - throw new RuntimeException("serialization operation is not supported"); - } - } - - public static Serializable deserialize(DataInputStream din) - throws IOException { - Serializable object = null; - int type = din.readInt(); - switch (type) { - case SERIAL_TYPE_NullableString: - object = NullableString.deserialize(din); - break; - case SERIAL_TYPE_TableVariable: - object = TableVariable.deserialize(din); - break; - case SERIAL_TYPE_Variable: - object = Variable.deserialize(din); - break; - case SERIAL_TYPE_StackFrame: - object = StackFrame.deserialize(din); - break; - case SERIAL_TYPE_DebugResponseSimple: - object = DebugResponseSimple.deserialize(din); - break; - case SERIAL_TYPE_DebugResponseCallgraph: - object = DebugResponseCallgraph.deserialize(din); - break; - case SERIAL_TYPE_DebugResponseStack: - object = DebugResponseStack.deserialize(din); - break; - case SERIAL_TYPE_DebugRequestType: - object = DebugRequestType.deserialize(din); - break; - case SERIAL_TYPE_DebugRequestStack: - object = DebugRequestStack.deserialize(din); - break; - case SERIAL_TYPE_DebugRequestLineBreakpointToggle: - object = DebugRequestLineBreakpointToggle.deserialize(din); - break; - case SERIAL_TYPE_DebugRequest: - object = DebugRequest.deserialize(din); - break; - case SERIAL_TYPE_DebugEventType: - object = DebugEventType.deserialize(din); - break; - case SERIAL_TYPE_DebugEventBreakpoint: - object = DebugEventBreakpoint.deserialize(din); - break; - case SERIAL_TYPE_DebugEventError: - object = DebugEventError.deserialize(din); - break; - case SERIAL_TYPE_DebugEvent: - object = DebugEvent.deserialize(din); - break; - default: - throw new RuntimeException("deserialization operation is not supported"); - } + static final int SERIAL_TYPE_DebugResponseVariables = 4; + static final int SERIAL_TYPE_DebugResponseSimple = 5; + static final int SERIAL_TYPE_StackFrame = 6; + static final int SERIAL_TYPE_DebugRequestType = 7; + static final int SERIAL_TYPE_DebugRequest = 8; + static final int SERIAL_TYPE_DebugRequestStack = 9; + static final int SERIAL_TYPE_DebugRequestLineBreakpointToggle = 10; + static final int SERIAL_TYPE_DebugEventType = 11; + static final int SERIAL_TYPE_DebugEvent = 12; + static final int SERIAL_TYPE_DebugEventBreakpoint = 13; + static final int SERIAL_TYPE_DebugEventError = 14; - return object; - } + public static void serialize(Serializable object, DataOutputStream dout) + throws IOException { + if (object instanceof NullableString) { + dout.writeInt(SERIAL_TYPE_NullableString); + NullableString.serialize(dout, (NullableString) object); + } else if (object instanceof TableVariable) { + dout.writeInt(SERIAL_TYPE_TableVariable); + TableVariable.serialize(dout, (TableVariable) object); + } else if (object instanceof Variable) { + dout.writeInt(SERIAL_TYPE_Variable); + Variable.serialize(dout, (Variable) object); + } else if (object instanceof StackFrame) { + dout.writeInt(SERIAL_TYPE_StackFrame); + StackFrame.serialize(dout, (StackFrame) object); + } else if (object instanceof DebugResponseSimple) { + dout.writeInt(SERIAL_TYPE_DebugResponseSimple); + DebugResponseSimple.serialize(dout, (DebugResponseSimple) object); + } else if (object instanceof DebugResponseVariables) { + dout.writeInt(SERIAL_TYPE_DebugResponseVariables); + DebugResponseVariables.serialize(dout, (DebugResponseVariables) object); + } else if (object instanceof DebugResponseCallgraph) { + dout.writeInt(SERIAL_TYPE_DebugResponseCallgraph); + DebugResponseCallgraph.serialize(dout, + (DebugResponseCallgraph) object); + } else if (object instanceof DebugRequestType) { + dout.writeInt(SERIAL_TYPE_DebugRequestType); + DebugRequestType.serialize(dout, (DebugRequestType) object); + } else if (object instanceof DebugRequestStack) { + dout.writeInt(SERIAL_TYPE_DebugRequestStack); + DebugRequestStack.serialize(dout, (DebugRequestStack) object); + } else if (object instanceof DebugRequestLineBreakpointToggle) { + dout.writeInt(SERIAL_TYPE_DebugRequestLineBreakpointToggle); + DebugRequestLineBreakpointToggle.serialize(dout, + (DebugRequestLineBreakpointToggle) object); + } else if (object instanceof DebugRequest) { + dout.writeInt(SERIAL_TYPE_DebugRequest); + DebugRequest.serialize(dout, (DebugRequest) object); + } else if (object instanceof DebugEventType) { + dout.writeInt(SERIAL_TYPE_DebugEventType); + DebugEventType.serialize(dout, (DebugEventType) object); + } else if (object instanceof DebugEventBreakpoint) { + dout.writeInt(SERIAL_TYPE_DebugEventBreakpoint); + DebugEventBreakpoint.serialize(dout, (DebugEventBreakpoint) object); + } else if (object instanceof DebugEventError) { + dout.writeInt(SERIAL_TYPE_DebugEventError); + DebugEventError.serialize(dout, (DebugEventError) object); + } else if (object instanceof DebugEvent) { + dout.writeInt(SERIAL_TYPE_DebugEvent); + DebugEvent.serialize(dout, (DebugEvent) object); + } else { + // catch the errors: forgot to implement + // serialization/deserialization + throw new RuntimeException( + "serialization operation is not supported"); + } + } + + public static Serializable deserialize(DataInputStream din) + throws IOException { + Serializable object = null; + int type = din.readInt(); + switch (type) { + case SERIAL_TYPE_NullableString: + object = NullableString.deserialize(din); + break; + case SERIAL_TYPE_TableVariable: + object = TableVariable.deserialize(din); + break; + case SERIAL_TYPE_Variable: + object = Variable.deserialize(din); + break; + case SERIAL_TYPE_StackFrame: + object = StackFrame.deserialize(din); + break; + case SERIAL_TYPE_DebugResponseSimple: + object = DebugResponseSimple.deserialize(din); + break; + case SERIAL_TYPE_DebugResponseCallgraph: + object = DebugResponseCallgraph.deserialize(din); + break; + case SERIAL_TYPE_DebugResponseVariables: + object = DebugResponseVariables.deserialize(din); + break; + case SERIAL_TYPE_DebugRequestType: + object = DebugRequestType.deserialize(din); + break; + case SERIAL_TYPE_DebugRequestStack: + object = DebugRequestStack.deserialize(din); + break; + case SERIAL_TYPE_DebugRequestLineBreakpointToggle: + object = DebugRequestLineBreakpointToggle.deserialize(din); + break; + case SERIAL_TYPE_DebugRequest: + object = DebugRequest.deserialize(din); + break; + case SERIAL_TYPE_DebugEventType: + object = DebugEventType.deserialize(din); + break; + case SERIAL_TYPE_DebugEventBreakpoint: + object = DebugEventBreakpoint.deserialize(din); + break; + case SERIAL_TYPE_DebugEventError: + object = DebugEventError.deserialize(din); + break; + case SERIAL_TYPE_DebugEvent: + object = DebugEvent.deserialize(din); + break; + default: + throw new RuntimeException( + "deserialization operation is not supported"); + } + + return object; + } } diff --git a/src/debug/org/luaj/debug/request/DebugRequestType.java b/src/debug/org/luaj/debug/request/DebugRequestType.java index bf30cd9a..0cff6a10 100644 --- a/src/debug/org/luaj/debug/request/DebugRequestType.java +++ b/src/debug/org/luaj/debug/request/DebugRequestType.java @@ -31,7 +31,7 @@ import org.luaj.debug.EnumType; public class DebugRequestType extends EnumType { public static final DebugRequestType start = new DebugRequestType("start", 0); public static final DebugRequestType resume = new DebugRequestType("resume", 1); - public static final DebugRequestType suspend = new DebugRequestType("suspend", 2); + public static final DebugRequestType suspend = new DebugRequestType("suspend", 2); public static final DebugRequestType exit = new DebugRequestType("exit", 3); public static final DebugRequestType lineBreakpointSet = new DebugRequestType("lineBreakpointSet", 4); public static final DebugRequestType lineBreakpointClear = new DebugRequestType("lineBreakpointClear", 5); @@ -42,32 +42,34 @@ public class DebugRequestType extends EnumType { public static final DebugRequestType stepInto = new DebugRequestType("stepInto", 10); public static final DebugRequestType stepOver = new DebugRequestType("stepOver", 11); public static final DebugRequestType stepReturn = new DebugRequestType("stepReturn", 12); + public static final DebugRequestType global = new DebugRequestType("global", 13); protected static final DebugRequestType[] ENUMS = new DebugRequestType[] { - start, - resume, - suspend, - exit, - lineBreakpointSet, - lineBreakpointClear, - watchpointSet, - watchpointClear, - callgraph, - stack, - stepInto, - stepOver, - stepReturn + start, + resume, + suspend, + exit, + lineBreakpointSet, + lineBreakpointClear, + watchpointSet, + watchpointClear, + callgraph, + stack, + stepInto, + stepOver, + stepReturn, + global }; public DebugRequestType(String name, int ordinal) { - super(name, ordinal); + super(name, ordinal); } public static DebugRequestType deserialize(DataInputStream in) throws IOException { - int ordinal = in.readInt(); - if (ordinal < 0 || ordinal >= ENUMS.length) { - throw new RuntimeException("DebugRequestType: ordinal is out of the range."); - } - return ENUMS[ordinal]; + int ordinal = in.readInt(); + if (ordinal < 0 || ordinal >= ENUMS.length) { + throw new RuntimeException("DebugRequestType: ordinal is out of the range."); + } + return ENUMS[ordinal]; } } diff --git a/src/debug/org/luaj/debug/response/DebugResponseStack.java b/src/debug/org/luaj/debug/response/DebugResponseVariables.java similarity index 65% rename from src/debug/org/luaj/debug/response/DebugResponseStack.java rename to src/debug/org/luaj/debug/response/DebugResponseVariables.java index fb1caae7..0b77c6ed 100644 --- a/src/debug/org/luaj/debug/response/DebugResponseStack.java +++ b/src/debug/org/luaj/debug/response/DebugResponseVariables.java @@ -28,16 +28,15 @@ import java.io.IOException; import org.luaj.debug.SerializationHelper; import org.luaj.debug.Variable; - -public class DebugResponseStack implements DebugResponse { +public class DebugResponseVariables implements DebugResponse { protected Variable[] variables; - public DebugResponseStack(Variable[] variables) { - if (variables == null) { - this.variables = new Variable[0]; - } else { - this.variables = variables; - } + public DebugResponseVariables(Variable[] variables) { + if (variables == null) { + this.variables = new Variable[0]; + } else { + this.variables = variables; + } } public Variable[] getVariables() { @@ -55,21 +54,23 @@ public class DebugResponseStack implements DebugResponse { return buffer.toString(); } - public static void serialize(DataOutputStream out, DebugResponseStack response) + public static void serialize(DataOutputStream out, + DebugResponseVariables response) throws IOException { - Variable[] variables = response.getVariables(); - out.writeInt(variables == null ? 0 : variables.length); - for (int i = 0; i < variables.length; i++) { - SerializationHelper.serialize(variables[i], out); - } - } - - public static DebugResponseStack deserialize(DataInputStream in) throws IOException { - int count = in.readInt(); - Variable[] variables = new Variable[count]; - for (int i = 0; i < count; i++) { - variables[i] = (Variable) SerializationHelper.deserialize(in); - } - return new DebugResponseStack(variables); - } + Variable[] variables = response.getVariables(); + out.writeInt(variables == null ? 0 : variables.length); + for (int i = 0; i < variables.length; i++) { + SerializationHelper.serialize(variables[i], out); + } + } + + public static DebugResponseVariables deserialize(DataInputStream in) + throws IOException { + int count = in.readInt(); + Variable[] variables = new Variable[count]; + for (int i = 0; i < count; i++) { + variables[i] = (Variable) SerializationHelper.deserialize(in); + } + return new DebugResponseVariables(variables); + } } diff --git a/src/test/java/org/luaj/debug/DebugResponseTest.java b/src/test/java/org/luaj/debug/DebugResponseTest.java index e89eb368..c9ba9c83 100644 --- a/src/test/java/org/luaj/debug/DebugResponseTest.java +++ b/src/test/java/org/luaj/debug/DebugResponseTest.java @@ -2,13 +2,10 @@ package org.luaj.debug; import java.io.IOException; -import org.luaj.debug.SerializationHelper; -import org.luaj.debug.StackFrame; -import org.luaj.debug.TableVariable; -import org.luaj.debug.Variable; + import org.luaj.debug.response.DebugResponseCallgraph; import org.luaj.debug.response.DebugResponseSimple; -import org.luaj.debug.response.DebugResponseStack; +import org.luaj.debug.response.DebugResponseVariables; import org.luaj.vm.Lua; import junit.framework.TestCase; @@ -51,10 +48,10 @@ public class DebugResponseTest extends TestCase { private void doTestDebugResponseStackSerialization(Variable[] variables) throws IOException { - DebugResponseStack stackIn = new DebugResponseStack(variables); + DebugResponseVariables stackIn = new DebugResponseVariables(variables); byte[] data = SerializationHelper.serialize(stackIn); - DebugResponseStack stackOut - = (DebugResponseStack) SerializationHelper.deserialize(data); + DebugResponseVariables stackOut + = (DebugResponseVariables) SerializationHelper.deserialize(data); Variable[] variablesIn = stackIn.getVariables(); Variable[] variablesOut = stackOut.getVariables(); assertNotNull(variablesIn);