|
|
|
|
@@ -53,23 +53,27 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
|
|
|
|
|
|
|
|
|
// stepping constants and stepping state
|
|
|
|
|
protected static final int STEP_NONE = 0;
|
|
|
|
|
|
|
|
|
|
protected static final int STEP_OVER = 1;
|
|
|
|
|
|
|
|
|
|
protected static final int STEP_INTO = 2;
|
|
|
|
|
|
|
|
|
|
protected static final int STEP_RETURN = 3;
|
|
|
|
|
|
|
|
|
|
protected int stepping = STEP_NONE;
|
|
|
|
|
protected boolean shouldPauseForStepping = false;
|
|
|
|
|
protected int steppingFrame = -1;
|
|
|
|
|
|
|
|
|
|
protected Hashtable breakpoints = new Hashtable();
|
|
|
|
|
protected boolean exiting = false;
|
|
|
|
|
protected boolean suspended = false;
|
|
|
|
|
protected boolean isStarted = false;
|
|
|
|
|
protected int lastline = -1;
|
|
|
|
|
protected String lastSource;
|
|
|
|
|
protected DebugSupport debugSupport;
|
|
|
|
|
protected VMException lastException;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public DebugStackState() {}
|
|
|
|
|
public DebugStackState() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void setDebugSupport(DebugSupport debugSupport) throws IOException {
|
|
|
|
|
if (debugSupport == null) {
|
|
|
|
|
@@ -105,7 +109,8 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
|
|
|
|
|
|
|
|
|
// override and fill in line number info
|
|
|
|
|
public void error(String message, int level) {
|
|
|
|
|
super.error( level<=0? message: getFileLine(cc+1-level)+": "+message );
|
|
|
|
|
super.error(level <= 0 ? message : getFileLine(cc + 1 - level) + ": "
|
|
|
|
|
+ message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// use line numbers by default
|
|
|
|
|
@@ -131,7 +136,6 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// debug hooks
|
|
|
|
|
public void debugHooks(int pc) {
|
|
|
|
|
if (exiting) {
|
|
|
|
|
@@ -142,10 +146,19 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
|
|
|
|
DebugUtils.println("entered debugHook on pc=" + pc + "...");
|
|
|
|
|
|
|
|
|
|
synchronized (this) {
|
|
|
|
|
while (!isStarted) {
|
|
|
|
|
try {
|
|
|
|
|
this.wait();
|
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CallInfo currentCallInfo = calls[cc];
|
|
|
|
|
Proto currentProto = currentCallInfo.closure.p;
|
|
|
|
|
|
|
|
|
|
// if we are not stepping, we keep going if the line doesn't change
|
|
|
|
|
// if we are not stepping, we would keep going if the line doesn't
|
|
|
|
|
// change
|
|
|
|
|
int line = getLineNumber(currentCallInfo);
|
|
|
|
|
String source = DebugUtils.getSourceFileName(currentProto.source);
|
|
|
|
|
if (!isStepping() && lastline == line && source.equals(lastSource)) {
|
|
|
|
|
@@ -157,8 +170,7 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
|
|
|
|
|
|
|
|
|
int i = currentProto.code[pc];
|
|
|
|
|
int opCode = StackState.GET_OPCODE(i);
|
|
|
|
|
if (isStepping() &&
|
|
|
|
|
opCode == StackState.OP_RETURN && cc == 0) {
|
|
|
|
|
if (isStepping() && opCode == StackState.OP_RETURN && cc == 0) {
|
|
|
|
|
cancelStepping();
|
|
|
|
|
} else if (shouldPauseForStepping) {
|
|
|
|
|
shouldPauseForStepping = false;
|
|
|
|
|
@@ -170,12 +182,13 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
|
|
|
|
shouldPauseForStepping = true;
|
|
|
|
|
}
|
|
|
|
|
} else if (stepping == STEP_OVER) {
|
|
|
|
|
if ((lastline != line && steppingFrame == cc) || (steppingFrame > cc)) {
|
|
|
|
|
if ((lastline != line && steppingFrame == cc)
|
|
|
|
|
|| (steppingFrame > cc)) {
|
|
|
|
|
suspendOnStepping();
|
|
|
|
|
}
|
|
|
|
|
} else if (stepping == STEP_RETURN) {
|
|
|
|
|
if ((opCode == StackState.OP_RETURN && cc == this.steppingFrame) ||
|
|
|
|
|
(opCode == StackState.OP_TAILCALL && cc == this.steppingFrame)){
|
|
|
|
|
if ((opCode == StackState.OP_RETURN && cc == this.steppingFrame)
|
|
|
|
|
|| (opCode == StackState.OP_TAILCALL && cc == this.steppingFrame)) {
|
|
|
|
|
shouldPauseForStepping = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -184,13 +197,15 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
|
|
|
|
if (!suspended && lastline != line) {
|
|
|
|
|
if (DebugUtils.IS_DEBUG)
|
|
|
|
|
DebugUtils.println("Source: " + currentProto.source);
|
|
|
|
|
|
|
|
|
|
String breakpointKey = constructBreakpointKey(source, line);
|
|
|
|
|
String fileName = DebugUtils.getSourceFileName(source);
|
|
|
|
|
String breakpointKey = constructBreakpointKey(fileName, line);
|
|
|
|
|
if (breakpoints.containsKey(breakpointKey)) {
|
|
|
|
|
if (DebugUtils.IS_DEBUG)
|
|
|
|
|
DebugUtils.println("hitting breakpoint " + constructBreakpointKey(source, line));
|
|
|
|
|
DebugUtils.println("hitting breakpoint "
|
|
|
|
|
+ constructBreakpointKey(fileName, line));
|
|
|
|
|
|
|
|
|
|
debugSupport.notifyDebugEvent(new DebugEventBreakpoint(source, line));
|
|
|
|
|
debugSupport.notifyDebugEvent(new DebugEventBreakpoint(
|
|
|
|
|
fileName, line));
|
|
|
|
|
suspended = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -221,27 +236,31 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void cancelStepping() {
|
|
|
|
|
debugSupport.notifyDebugEvent(new DebugEvent(DebugEventType.resumedOnSteppingEnd));
|
|
|
|
|
debugSupport.notifyDebugEvent(new DebugEvent(
|
|
|
|
|
DebugEventType.resumedOnSteppingEnd));
|
|
|
|
|
stepping = STEP_NONE;
|
|
|
|
|
steppingFrame = -1;
|
|
|
|
|
shouldPauseForStepping = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void suspendOnStepping() {
|
|
|
|
|
debugSupport.notifyDebugEvent(new DebugEvent(DebugEventType.suspendedOnStepping));
|
|
|
|
|
debugSupport.notifyDebugEvent(new DebugEvent(
|
|
|
|
|
DebugEventType.suspendedOnStepping));
|
|
|
|
|
suspended = true;
|
|
|
|
|
steppingFrame = -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the current line number
|
|
|
|
|
*
|
|
|
|
|
* @param pc program counter
|
|
|
|
|
* @return the line number corresponding to the pc
|
|
|
|
|
*/
|
|
|
|
|
private int getLineNumber(CallInfo ci) {
|
|
|
|
|
int[] lineNumbers = ci.closure.p.lineinfo;
|
|
|
|
|
int pc = ci.pc;
|
|
|
|
|
int line = (lineNumbers != null && lineNumbers.length > pc ? lineNumbers[pc] : -1);
|
|
|
|
|
int line = (lineNumbers != null && lineNumbers.length > pc ? lineNumbers[pc]
|
|
|
|
|
: -1);
|
|
|
|
|
return line;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -249,16 +268,19 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
|
|
|
|
|
|
|
|
|
public DebugResponse handleRequest(DebugRequest request) {
|
|
|
|
|
if (this.debugSupport == null) {
|
|
|
|
|
throw new IllegalStateException("DebugStackState is not equiped with DebugSupport.");
|
|
|
|
|
throw new IllegalStateException(
|
|
|
|
|
"DebugStackState is not equiped with DebugSupport.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (DebugUtils.IS_DEBUG)
|
|
|
|
|
DebugUtils.println("DebugStackState is handling request: " + request.toString());
|
|
|
|
|
DebugUtils.println("DebugStackState is handling request: "
|
|
|
|
|
+ request.toString());
|
|
|
|
|
|
|
|
|
|
DebugRequestType requestType = request.getType();
|
|
|
|
|
if (DebugRequestType.start == requestType) {
|
|
|
|
|
DebugEvent event = new DebugEvent(DebugEventType.started);
|
|
|
|
|
debugSupport.notifyDebugEvent(event);
|
|
|
|
|
setStarted();
|
|
|
|
|
return DebugResponseSimple.SUCCESS;
|
|
|
|
|
} else if (DebugRequestType.exit == requestType) {
|
|
|
|
|
stop();
|
|
|
|
|
@@ -274,14 +296,14 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
|
|
|
|
debugSupport.notifyDebugEvent(event);
|
|
|
|
|
return DebugResponseSimple.SUCCESS;
|
|
|
|
|
} else if (DebugRequestType.lineBreakpointSet == requestType) {
|
|
|
|
|
DebugRequestLineBreakpointToggle setBreakpointRequest
|
|
|
|
|
= (DebugRequestLineBreakpointToggle)request;
|
|
|
|
|
setBreakpoint(setBreakpointRequest.getSource(), setBreakpointRequest.getLineNumber());
|
|
|
|
|
DebugRequestLineBreakpointToggle setBreakpointRequest = (DebugRequestLineBreakpointToggle) request;
|
|
|
|
|
setBreakpoint(setBreakpointRequest.getSource(),
|
|
|
|
|
setBreakpointRequest.getLineNumber());
|
|
|
|
|
return DebugResponseSimple.SUCCESS;
|
|
|
|
|
} else if (DebugRequestType.lineBreakpointClear == requestType) {
|
|
|
|
|
DebugRequestLineBreakpointToggle clearBreakpointRequest
|
|
|
|
|
= (DebugRequestLineBreakpointToggle)request;
|
|
|
|
|
clearBreakpoint(clearBreakpointRequest.getSource(), clearBreakpointRequest.getLineNumber());
|
|
|
|
|
DebugRequestLineBreakpointToggle clearBreakpointRequest = (DebugRequestLineBreakpointToggle) request;
|
|
|
|
|
clearBreakpoint(clearBreakpointRequest.getSource(),
|
|
|
|
|
clearBreakpointRequest.getLineNumber());
|
|
|
|
|
return DebugResponseSimple.SUCCESS;
|
|
|
|
|
} else if (DebugRequestType.callgraph == requestType) {
|
|
|
|
|
return new DebugResponseCallgraph(getCallgraph());
|
|
|
|
|
@@ -290,23 +312,27 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
|
|
|
|
int index = stackRequest.getIndex();
|
|
|
|
|
return new DebugResponseStack(getStack(index));
|
|
|
|
|
} else if (DebugRequestType.stepInto == requestType) {
|
|
|
|
|
DebugEvent event = new DebugEvent(DebugEventType.resumedOnSteppingInto);
|
|
|
|
|
DebugEvent event = new DebugEvent(
|
|
|
|
|
DebugEventType.resumedOnSteppingInto);
|
|
|
|
|
debugSupport.notifyDebugEvent(event);
|
|
|
|
|
stepInto();
|
|
|
|
|
return DebugResponseSimple.SUCCESS;
|
|
|
|
|
} else if (DebugRequestType.stepOver == requestType) {
|
|
|
|
|
DebugEvent event = new DebugEvent(DebugEventType.resumedOnSteppingOver);
|
|
|
|
|
DebugEvent event = new DebugEvent(
|
|
|
|
|
DebugEventType.resumedOnSteppingOver);
|
|
|
|
|
debugSupport.notifyDebugEvent(event);
|
|
|
|
|
stepOver();
|
|
|
|
|
return DebugResponseSimple.SUCCESS;
|
|
|
|
|
} else if (DebugRequestType.stepReturn == requestType) {
|
|
|
|
|
DebugEvent event = new DebugEvent(DebugEventType.resumedOnSteppingReturn);
|
|
|
|
|
DebugEvent event = new DebugEvent(
|
|
|
|
|
DebugEventType.resumedOnSteppingReturn);
|
|
|
|
|
debugSupport.notifyDebugEvent(event);
|
|
|
|
|
stepReturn();
|
|
|
|
|
return DebugResponseSimple.SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
throw new java.lang.IllegalArgumentException( "unkown request type: "+ request.getType());
|
|
|
|
|
throw new java.lang.IllegalArgumentException("unkown request type: "
|
|
|
|
|
+ request.getType());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -321,6 +347,13 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void setStarted() {
|
|
|
|
|
synchronized (this) {
|
|
|
|
|
isStarted = true;
|
|
|
|
|
this.notify();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* resume the execution
|
|
|
|
|
*/
|
|
|
|
|
@@ -334,7 +367,8 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
|
|
|
|
|
|
|
|
|
public void stop() {
|
|
|
|
|
if (this.debugSupport == null) {
|
|
|
|
|
throw new IllegalStateException("DebugStackState is not equiped with DebugSupport.");
|
|
|
|
|
throw new IllegalStateException(
|
|
|
|
|
"DebugStackState is not equiped with DebugSupport.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DebugEvent event = new DebugEvent(DebugEventType.terminated);
|
|
|
|
|
@@ -362,18 +396,18 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* set breakpoint at line N
|
|
|
|
|
* @param N the line to set the breakpoint at
|
|
|
|
|
*
|
|
|
|
|
* @param N
|
|
|
|
|
* the line to set the breakpoint at
|
|
|
|
|
*/
|
|
|
|
|
public void setBreakpoint(String source, int lineNumber) {
|
|
|
|
|
if (DebugUtils.IS_DEBUG) {
|
|
|
|
|
DebugUtils.print("source: " + source + " line:" + lineNumber);
|
|
|
|
|
DebugUtils.println("adding breakpoint " + constructBreakpointKey(source, lineNumber));
|
|
|
|
|
}
|
|
|
|
|
String fileName = DebugUtils.getSourceFileName(source);
|
|
|
|
|
String breakpointKey = constructBreakpointKey(fileName, lineNumber);
|
|
|
|
|
|
|
|
|
|
synchronized ( this ) {
|
|
|
|
|
String normalizedFileName = DebugUtils.getSourceFileName(source);
|
|
|
|
|
breakpoints.put(constructBreakpointKey(normalizedFileName, lineNumber), Boolean.TRUE );
|
|
|
|
|
}
|
|
|
|
|
if (DebugUtils.IS_DEBUG)
|
|
|
|
|
DebugUtils.println("adding breakpoint " + breakpointKey);
|
|
|
|
|
|
|
|
|
|
breakpoints.put(breakpointKey, Boolean.TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected String constructBreakpointKey(String source, int lineNumber) {
|
|
|
|
|
@@ -384,17 +418,18 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
|
|
|
|
* clear breakpoint at line lineNumber of source source
|
|
|
|
|
*/
|
|
|
|
|
public void clearBreakpoint(String source, int lineNumber) {
|
|
|
|
|
String fileName = DebugUtils.getSourceFileName(source);
|
|
|
|
|
String breakpointKey = constructBreakpointKey(fileName, lineNumber);
|
|
|
|
|
|
|
|
|
|
if (DebugUtils.IS_DEBUG)
|
|
|
|
|
DebugUtils.println("removing breakpoint " + constructBreakpointKey(source, lineNumber));
|
|
|
|
|
synchronized ( this ) {
|
|
|
|
|
String normalizedFileName = DebugUtils.getSourceFileName(source);
|
|
|
|
|
breakpoints.remove(constructBreakpointKey(normalizedFileName, lineNumber));
|
|
|
|
|
}
|
|
|
|
|
DebugUtils.println("removing breakpoint " + breakpointKey);
|
|
|
|
|
|
|
|
|
|
breakpoints.remove(breakpointKey);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* return the current call graph (i.e. stack frames from
|
|
|
|
|
* old to new, include information about file, method, etc.)
|
|
|
|
|
* return the current call graph (i.e. stack frames from old to new, include
|
|
|
|
|
* information about file, method, etc.)
|
|
|
|
|
*/
|
|
|
|
|
public StackFrame[] getCallgraph() {
|
|
|
|
|
int n = cc;
|
|
|
|
|
@@ -412,71 +447,103 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
|
|
|
|
|
|
|
|
|
public Variable[] getStack(int index) {
|
|
|
|
|
if (index < 0 || index >= calls.length) {
|
|
|
|
|
//TODO: this is an error, handle it differently
|
|
|
|
|
return new Variable[0];
|
|
|
|
|
throw new RuntimeException("invalid stack index");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CallInfo callInfo = calls[index];
|
|
|
|
|
if(DebugUtils.IS_DEBUG)
|
|
|
|
|
DebugUtils.println("Stack Frame: " + index + "[" + callInfo.base + "," + callInfo.top + "]");
|
|
|
|
|
int top = callInfo.top < callInfo.base ? callInfo.base : callInfo.top;
|
|
|
|
|
Proto prototype = callInfo.closure.p;
|
|
|
|
|
LocVars[] localVariables = prototype.locvars;
|
|
|
|
|
Vector variables = new Vector();
|
|
|
|
|
int localVariableCount = 0;
|
|
|
|
|
Hashtable variablesSeen = new Hashtable();
|
|
|
|
|
for (int i = 0; localVariables != null && i < localVariables.length && i <= top; i++) {
|
|
|
|
|
String varName = localVariables[i].varname.toString();
|
|
|
|
|
if(DebugUtils.IS_DEBUG) {
|
|
|
|
|
DebugUtils.print("\tVariable: " + varName);
|
|
|
|
|
DebugUtils.print("\tValue: " + stack[callInfo.base + i]);
|
|
|
|
|
}
|
|
|
|
|
if (!variablesSeen.contains(varName) &&
|
|
|
|
|
!LexState.isReservedKeyword(varName)) {
|
|
|
|
|
variablesSeen.put(varName, varName);
|
|
|
|
|
LValue value = stack[callInfo.base + i];
|
|
|
|
|
if (value != null) {
|
|
|
|
|
int type = value.luaGetType();
|
|
|
|
|
if (DebugUtils.IS_DEBUG)
|
|
|
|
|
DebugUtils.print("\tType: " + Lua.TYPE_NAMES[type]);
|
|
|
|
|
if (type == Lua.LUA_TTABLE) {
|
|
|
|
|
if (DebugUtils.IS_DEBUG)
|
|
|
|
|
DebugUtils.println(" (selected)");
|
|
|
|
|
variables.addElement(
|
|
|
|
|
new TableVariable(localVariableCount++,
|
|
|
|
|
varName,
|
|
|
|
|
type,
|
|
|
|
|
(LTable) value));
|
|
|
|
|
} else if (type != Lua.LUA_TFUNCTION &&
|
|
|
|
|
type != LUA_TTHREAD) {
|
|
|
|
|
if (DebugUtils.IS_DEBUG)
|
|
|
|
|
DebugUtils.println(" (selected)");
|
|
|
|
|
variables.addElement(
|
|
|
|
|
new Variable(localVariableCount++,
|
|
|
|
|
varName,
|
|
|
|
|
type,
|
|
|
|
|
value.toString()));
|
|
|
|
|
} else {
|
|
|
|
|
if (DebugUtils.IS_DEBUG)
|
|
|
|
|
DebugUtils.println("");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (DebugUtils.IS_DEBUG)
|
|
|
|
|
DebugUtils.println("");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (DebugUtils.IS_DEBUG)
|
|
|
|
|
DebugUtils.println("");
|
|
|
|
|
}
|
|
|
|
|
for (int i = index; i >= 0; 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String getVariable(CallInfo callInfo, int index) {
|
|
|
|
|
Proto prototype = callInfo.closure.p;
|
|
|
|
|
int count = -1;
|
|
|
|
|
LocVars[] localVariables = prototype.locvars;
|
|
|
|
|
for (int i = 0; i < localVariables.length; i++) {
|
|
|
|
|
if (callInfo.pc < localVariables[i].startpc ||
|
|
|
|
|
callInfo.pc > localVariables[i].endpc) {
|
|
|
|
|
continue;
|
|
|
|
|
} else {
|
|
|
|
|
count++;
|
|
|
|
|
if (count == index) {
|
|
|
|
|
return localVariables[i].varname.toJavaString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void addVariables(Vector variables, Hashtable variablesSeen, int index) {
|
|
|
|
|
CallInfo callInfo = calls[index];
|
|
|
|
|
Proto prototype = callInfo.closure.p;
|
|
|
|
|
int base = callInfo.base;
|
|
|
|
|
int top = callInfo.top < callInfo.base ? callInfo.base+1 : callInfo.top;
|
|
|
|
|
|
|
|
|
|
if (DebugUtils.IS_DEBUG) {
|
|
|
|
|
DebugUtils.println("Stack Frame: " + index + " [" + base + "," + top + "], # of localvars: " + prototype.locvars.length + ", pc=" + callInfo.pc);
|
|
|
|
|
for (int i = 0; i < prototype.locvars.length; i++) {
|
|
|
|
|
DebugUtils.println("localvars[" + i + "]: " + prototype.locvars[i].varname + "(" + prototype.locvars[i].startpc + "," + prototype.locvars[i].endpc + ")");
|
|
|
|
|
}
|
|
|
|
|
for (int i = base; i < top; i++){
|
|
|
|
|
DebugUtils.println("stack[" + i + "]=" + stack[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int selectedVariableCount = 0;
|
|
|
|
|
for (int i = base; i < top; i++) {
|
|
|
|
|
String varName = getVariable(callInfo, i-base);
|
|
|
|
|
if (varName == null) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(DebugUtils.IS_DEBUG) {
|
|
|
|
|
DebugUtils.print("\tVariable: " + varName);
|
|
|
|
|
DebugUtils.print("\tValue: " + stack[i]);
|
|
|
|
|
}
|
|
|
|
|
if (!variablesSeen.contains(varName) &&
|
|
|
|
|
!LexState.isReservedKeyword(varName)) {
|
|
|
|
|
variablesSeen.put(varName, varName);
|
|
|
|
|
LValue value = stack[i];
|
|
|
|
|
if (value != null) {
|
|
|
|
|
int type = value.luaGetType();
|
|
|
|
|
if (DebugUtils.IS_DEBUG)
|
|
|
|
|
DebugUtils.print("\tType: " + Lua.TYPE_NAMES[type]);
|
|
|
|
|
if (type == Lua.LUA_TTABLE) {
|
|
|
|
|
if (DebugUtils.IS_DEBUG)
|
|
|
|
|
DebugUtils.print(" (selected)");
|
|
|
|
|
variables.addElement(
|
|
|
|
|
new TableVariable(selectedVariableCount++,
|
|
|
|
|
varName,
|
|
|
|
|
type,
|
|
|
|
|
(LTable) value));
|
|
|
|
|
} else if (type == LUA_TTHREAD) {
|
|
|
|
|
// coroutines
|
|
|
|
|
} else if (type != LUA_TFUNCTION) {
|
|
|
|
|
if (DebugUtils.IS_DEBUG)
|
|
|
|
|
DebugUtils.print(" (selected)");
|
|
|
|
|
variables.addElement(
|
|
|
|
|
new Variable(selectedVariableCount++,
|
|
|
|
|
varName,
|
|
|
|
|
type,
|
|
|
|
|
value.toString()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (DebugUtils.IS_DEBUG)
|
|
|
|
|
DebugUtils.println("");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* step over to next line
|
|
|
|
|
|