From 8eab291c9bf13b12c016343f0aeb7de683344d46 Mon Sep 17 00:00:00 2001 From: Shu Lei Date: Wed, 10 Oct 2007 00:26:23 +0000 Subject: [PATCH] make the debugging support code compile under JDK 1.3 --- src/main/java/lua/GlobalState.java | 2 +- src/main/java/lua/debug/DebugEvent.java | 1 - .../java/lua/debug/DebugEventBreakpoint.java | 1 - src/main/java/lua/debug/DebugEventError.java | 1 - src/main/java/lua/debug/DebugEventType.java | 28 +- src/main/java/lua/debug/DebugRequest.java | 1 - .../DebugRequestLineBreakpointToggle.java | 1 - .../java/lua/debug/DebugRequestStack.java | 1 - src/main/java/lua/debug/DebugRequestType.java | 28 +- .../debug/DebugRequestWatchpointToggle.java | 21 +- .../lua/debug/DebugResponseCallgraph.java | 13 +- .../java/lua/debug/DebugResponseSimple.java | 1 - .../java/lua/debug/DebugResponseStack.java | 1 - src/main/java/lua/debug/DebugStackState.java | 37 +-- src/main/java/lua/debug/DebugSupport.java | 14 +- src/main/java/lua/debug/DebugUtils.java | 2 +- src/main/java/lua/debug/EnumType.java | 63 ++++ src/main/java/lua/debug/StackFrame.java | 1 - src/main/java/lua/debug/StandardLuaJVM.java | 305 ++++++++++++++++++ src/main/java/lua/debug/Variable.java | 4 - src/test/java/lua/debug/LuaJVMTest.java | 8 +- 21 files changed, 454 insertions(+), 80 deletions(-) create mode 100644 src/main/java/lua/debug/EnumType.java create mode 100644 src/main/java/lua/debug/StandardLuaJVM.java diff --git a/src/main/java/lua/GlobalState.java b/src/main/java/lua/GlobalState.java index 35f6e1cf..6eab26e4 100644 --- a/src/main/java/lua/GlobalState.java +++ b/src/main/java/lua/GlobalState.java @@ -29,7 +29,7 @@ public class GlobalState { resetGlobals(); } - static void resetGlobals() { + static public void resetGlobals() { _G = new LTable(); _G .put( "_G", _G ); Builtin.addBuiltins( _G ); diff --git a/src/main/java/lua/debug/DebugEvent.java b/src/main/java/lua/debug/DebugEvent.java index a5ce3898..963de75a 100644 --- a/src/main/java/lua/debug/DebugEvent.java +++ b/src/main/java/lua/debug/DebugEvent.java @@ -43,7 +43,6 @@ public class DebugEvent implements Serializable { /* (non-Javadoc) * @see java.lang.Object#toString() */ - @Override public String toString() { return type.toString(); } diff --git a/src/main/java/lua/debug/DebugEventBreakpoint.java b/src/main/java/lua/debug/DebugEventBreakpoint.java index 4179f2c1..2da5921c 100644 --- a/src/main/java/lua/debug/DebugEventBreakpoint.java +++ b/src/main/java/lua/debug/DebugEventBreakpoint.java @@ -43,7 +43,6 @@ public class DebugEventBreakpoint extends DebugEvent { /* (non-Javadoc) * @see lua.debug.DebugEvent#toString() */ - @Override public String toString() { return super.toString() + " source:" + getSource() + " line:" + getLineNumber(); } diff --git a/src/main/java/lua/debug/DebugEventError.java b/src/main/java/lua/debug/DebugEventError.java index ff2bb171..2119ee02 100644 --- a/src/main/java/lua/debug/DebugEventError.java +++ b/src/main/java/lua/debug/DebugEventError.java @@ -37,7 +37,6 @@ public class DebugEventError extends DebugEvent { /* (non-Javadoc) * @see lua.debug.DebugEvent#toString() */ - @Override public String toString() { return super.toString() + " detail: " + getDetail(); } diff --git a/src/main/java/lua/debug/DebugEventType.java b/src/main/java/lua/debug/DebugEventType.java index 16e41c97..5f94e5a3 100644 --- a/src/main/java/lua/debug/DebugEventType.java +++ b/src/main/java/lua/debug/DebugEventType.java @@ -21,16 +21,20 @@ ******************************************************************************/ package lua.debug; -public enum DebugEventType { - started, - suspendedByClient, - suspendedOnBreakpoint, - suspendedOnWatchpoint, - suspendedOnStepping, - suspendedOnError, - resumedByClient, - resumedOnStepping, - resumedOnError, - error, - terminated +public class DebugEventType extends EnumType { + public static DebugEventType started = new DebugEventType("started", 0); + public static DebugEventType suspendedByClient = new DebugEventType("suspendedByClient", 1); + public static DebugEventType suspendedOnBreakpoint = new DebugEventType("suspendedOnBreakpoint", 2); + public static DebugEventType suspendedOnWatchpoint = new DebugEventType("suspendedOnWatchpoint", 3); + public static DebugEventType suspendedOnStepping = new DebugEventType("suspendedOnStepping", 4); + public static DebugEventType suspendedOnError = new DebugEventType("suspendedOnError", 5); + public static DebugEventType resumedByClient = new DebugEventType("resumedByClient", 6); + public static DebugEventType resumedOnStepping = new DebugEventType("resumedOnStepping", 7); + public static DebugEventType resumedOnError = new DebugEventType("resumedOnError", 8); + public static DebugEventType error = new DebugEventType("error", 9); + public static DebugEventType terminated = new DebugEventType("terminated", 10); + + protected DebugEventType(String name, int ordinal) { + super(name, ordinal); + } } diff --git a/src/main/java/lua/debug/DebugRequest.java b/src/main/java/lua/debug/DebugRequest.java index a6900b9d..a3490bcc 100644 --- a/src/main/java/lua/debug/DebugRequest.java +++ b/src/main/java/lua/debug/DebugRequest.java @@ -38,7 +38,6 @@ public class DebugRequest implements Serializable { /* (non-Javadoc) * @see java.lang.Object#toString() */ - @Override public String toString() { return type.toString(); } diff --git a/src/main/java/lua/debug/DebugRequestLineBreakpointToggle.java b/src/main/java/lua/debug/DebugRequestLineBreakpointToggle.java index 8662fcb1..4b2a9279 100644 --- a/src/main/java/lua/debug/DebugRequestLineBreakpointToggle.java +++ b/src/main/java/lua/debug/DebugRequestLineBreakpointToggle.java @@ -46,7 +46,6 @@ public class DebugRequestLineBreakpointToggle extends DebugRequest { /* (non-Javadoc) * @see lua.debug.DebugRequest#toString() */ - @Override public String toString() { return super.toString() + " Source:" + getSource() + " lineNumber:" + getLineNumber(); } diff --git a/src/main/java/lua/debug/DebugRequestStack.java b/src/main/java/lua/debug/DebugRequestStack.java index 17355e96..95eabd90 100644 --- a/src/main/java/lua/debug/DebugRequestStack.java +++ b/src/main/java/lua/debug/DebugRequestStack.java @@ -37,7 +37,6 @@ public class DebugRequestStack extends DebugRequest { /* (non-Javadoc) * @see lua.debug.DebugRequest#toString() */ - @Override public String toString() { return super.toString() + " stack frame:" + getIndex(); } diff --git a/src/main/java/lua/debug/DebugRequestType.java b/src/main/java/lua/debug/DebugRequestType.java index fd0136cf..9c0d4f38 100644 --- a/src/main/java/lua/debug/DebugRequestType.java +++ b/src/main/java/lua/debug/DebugRequestType.java @@ -21,15 +21,21 @@ ******************************************************************************/ package lua.debug; -public enum DebugRequestType { - suspend, - resume, - exit, - lineBreakpointSet, - lineBreakpointClear, - watchpointSet, - watchpointClear, - callgraph, - stack, - step +public class DebugRequestType extends EnumType { + private static final long serialVersionUID = 2829883820534540402L; + + public static final DebugRequestType suspend = new DebugRequestType("suspend", 0); + public static final DebugRequestType resume = new DebugRequestType("resume", 1); + public static final DebugRequestType exit = new DebugRequestType("exit", 2); + public static final DebugRequestType lineBreakpointSet = new DebugRequestType("lineBreakpointSet", 3); + public static final DebugRequestType lineBreakpointClear = new DebugRequestType("lineBreakpointClear", 4); + public static final DebugRequestType watchpointSet = new DebugRequestType("watchpointSet", 5); + public static final DebugRequestType watchpointClear = new DebugRequestType("watchpointClear", 6); + public static final DebugRequestType callgraph = new DebugRequestType("callgraph", 7); + public static final DebugRequestType stack = new DebugRequestType("stack", 8); + public static final DebugRequestType step = new DebugRequestType("step", 9); + + public DebugRequestType(String name, int ordinal) { + super(name, ordinal); + } } diff --git a/src/main/java/lua/debug/DebugRequestWatchpointToggle.java b/src/main/java/lua/debug/DebugRequestWatchpointToggle.java index d43f1913..589ce77b 100644 --- a/src/main/java/lua/debug/DebugRequestWatchpointToggle.java +++ b/src/main/java/lua/debug/DebugRequestWatchpointToggle.java @@ -24,11 +24,17 @@ package lua.debug; public class DebugRequestWatchpointToggle extends DebugRequest { private static final long serialVersionUID = -2978341358052851046L; - public enum AccessType { - Ignore, - Read, - Modify, - ReadAndModify + public static class AccessType extends EnumType { + private static final long serialVersionUID = 3523086189648091587L; + + public static final AccessType Ignore = new AccessType("Ignore", 0); + public static final AccessType Read = new AccessType("Read", 1); + public static final AccessType Modify = new AccessType("Modify", 2); + public static final AccessType ReadAndModify = new AccessType("ReadAndModify", 3); + + protected AccessType(String name, int ordinal) { + super(name, ordinal); + } }; protected String functionName; @@ -37,7 +43,9 @@ public class DebugRequestWatchpointToggle extends DebugRequest { public DebugRequestWatchpointToggle(String functionName, String variableName, AccessType accessType) { - super(accessType == AccessType.Ignore ? DebugRequestType.watchpointClear : DebugRequestType.watchpointSet); + super(accessType == AccessType.Ignore ? + DebugRequestType.watchpointClear : + DebugRequestType.watchpointSet); this.functionName = functionName; this.variableName = variableName; } @@ -53,7 +61,6 @@ public class DebugRequestWatchpointToggle extends DebugRequest { /* (non-Javadoc) * @see lua.debug.DebugRequest#toString() */ - @Override public String toString() { return super.toString() + " functionName:" + getFunctionName() + " variableName:" + getVariableName(); } diff --git a/src/main/java/lua/debug/DebugResponseCallgraph.java b/src/main/java/lua/debug/DebugResponseCallgraph.java index ae2aabc8..a08d2f19 100644 --- a/src/main/java/lua/debug/DebugResponseCallgraph.java +++ b/src/main/java/lua/debug/DebugResponseCallgraph.java @@ -34,17 +34,12 @@ public class DebugResponseCallgraph extends DebugResponseSimple { return this.stackFrames; } - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override public String toString() { StringBuilder buffer = new StringBuilder(); - if (this.stackFrames != null) { - for (StackFrame frame : stackFrames) { - buffer.append(frame.toString()); - buffer.append("\n"); - } + for (int i = 0; stackFrames != null && i < stackFrames.length; i++) { + StackFrame frame = stackFrames[i]; + buffer.append(frame.toString()); + buffer.append("\n"); } return buffer.toString(); } diff --git a/src/main/java/lua/debug/DebugResponseSimple.java b/src/main/java/lua/debug/DebugResponseSimple.java index 9da9f07f..1d52380d 100644 --- a/src/main/java/lua/debug/DebugResponseSimple.java +++ b/src/main/java/lua/debug/DebugResponseSimple.java @@ -42,7 +42,6 @@ public class DebugResponseSimple implements DebugResponse, Serializable { /* (non-Javadoc) * @see java.lang.Object#toString() */ - @Override public String toString() { return String.valueOf(isSuccessful); } diff --git a/src/main/java/lua/debug/DebugResponseStack.java b/src/main/java/lua/debug/DebugResponseStack.java index 4c5127be..a95c9fc9 100644 --- a/src/main/java/lua/debug/DebugResponseStack.java +++ b/src/main/java/lua/debug/DebugResponseStack.java @@ -37,7 +37,6 @@ public class DebugResponseStack extends DebugResponseSimple { /* (non-Javadoc) * @see java.lang.Object#toString() */ - @Override public String toString() { StringBuilder buffer = new StringBuilder(); for (int i = 0; variables != null && i < variables.length; i++) { diff --git a/src/main/java/lua/debug/DebugStackState.java b/src/main/java/lua/debug/DebugStackState.java index 29926db5..fce7900e 100644 --- a/src/main/java/lua/debug/DebugStackState.java +++ b/src/main/java/lua/debug/DebugStackState.java @@ -41,13 +41,12 @@ public class DebugStackState extends StackState implements DebugRequestListener private static final boolean DEBUG = false; - protected Map breakpoints = new HashMap(); + protected Map breakpoints = new HashMap(); protected boolean exiting = false; protected boolean suspended = false; protected boolean stepping = false; protected int lastline = -1; - protected List debugEventListeners - = new ArrayList(); + protected List debugEventListeners = new ArrayList(); public DebugStackState() { } @@ -70,9 +69,10 @@ public class DebugStackState extends StackState implements DebugRequestListener } protected void notifyDebugEventListeners(DebugEvent event) { - for (DebugEventListener listener : debugEventListeners) { + for (int i = 0; debugEventListeners != null && i < debugEventListeners.size(); i++) { + DebugEventListener listener = (DebugEventListener)debugEventListeners.get(i); listener.notifyDebugEvent(event); - } + } } private String getFileLine(int cindex) { @@ -183,37 +183,38 @@ public class DebugStackState extends StackState implements DebugRequestListener public DebugResponse handleRequest(DebugRequest request) { DebugUtils.println("DebugStackState is handling request: " + request.toString()); - switch (request.getType()) { - case suspend: - suspend(); + DebugRequestType requestType = request.getType(); + if (DebugRequestType.suspend == requestType) { + suspend(); return DebugResponseSimple.SUCCESS; - case resume: + } else if (DebugRequestType.resume == requestType) { resume(); return DebugResponseSimple.SUCCESS; - case exit: + } else if (DebugRequestType.exit == requestType) { exit(); return DebugResponseSimple.SUCCESS; - case lineBreakpointSet: + } else if (DebugRequestType.lineBreakpointSet == requestType) { DebugRequestLineBreakpointToggle setBreakpointRequest = (DebugRequestLineBreakpointToggle)request; setBreakpoint(setBreakpointRequest.getSource(), setBreakpointRequest.getLineNumber()); return DebugResponseSimple.SUCCESS; - case lineBreakpointClear: + } else if (DebugRequestType.lineBreakpointClear == requestType) { DebugRequestLineBreakpointToggle clearBreakpointRequest = (DebugRequestLineBreakpointToggle)request; clearBreakpoint(clearBreakpointRequest.getSource(), clearBreakpointRequest.getLineNumber()); return DebugResponseSimple.SUCCESS; - case callgraph: + } else if (DebugRequestType.callgraph == requestType) { return new DebugResponseCallgraph(getCallgraph()); - case stack: + } else if (DebugRequestType.stack == requestType) { DebugRequestStack stackRequest = (DebugRequestStack) request; int index = stackRequest.getIndex(); return new DebugResponseStack(getStack(index)); - case step: + } else if (DebugRequestType.step == requestType) { step(); return DebugResponseSimple.SUCCESS; } - throw new java.lang.IllegalArgumentException( "unkown request type: "+request.getType() ); + + throw new java.lang.IllegalArgumentException( "unkown request type: "+ request.getType()); } /** @@ -303,9 +304,9 @@ public class DebugStackState extends StackState implements DebugRequestListener int top = callInfo.top < callInfo.base ? callInfo.base : callInfo.top; Proto prototype = callInfo.closure.p; LocVars[] localVariables = prototype.locvars; - List variables = new ArrayList(); + List variables = new ArrayList(); int localVariableCount = 0; - Set variablesSeen = new HashSet(); + Set variablesSeen = new HashSet(); for (int i = 0; localVariables != null && i < localVariables.length && i <= top; i++) { String varName = localVariables[i].varname.toString(); DebugUtils.print("\tVariable: " + varName); diff --git a/src/main/java/lua/debug/DebugSupport.java b/src/main/java/lua/debug/DebugSupport.java index 5c115e16..816e63ad 100644 --- a/src/main/java/lua/debug/DebugSupport.java +++ b/src/main/java/lua/debug/DebugSupport.java @@ -29,10 +29,16 @@ import java.net.ServerSocket; import java.net.Socket; public class DebugSupport implements DebugEventListener { - public enum State { - UNKNOWN, - RUNNING, - STOPPED + public static class State extends EnumType { + private static final long serialVersionUID = 3657364516937093612L; + + public static final State UNKNOWN = new State("UNKNOWN", 0); + public static final State RUNNING = new State("RUNNING", 1); + public static final State STOPPED = new State("STOPPED", 2); + + public State(String name, int ordinal) { + super(name, ordinal); + } } protected DebugRequestListener listener; diff --git a/src/main/java/lua/debug/DebugUtils.java b/src/main/java/lua/debug/DebugUtils.java index 61d45219..898211c7 100644 --- a/src/main/java/lua/debug/DebugUtils.java +++ b/src/main/java/lua/debug/DebugUtils.java @@ -27,7 +27,7 @@ import lua.io.LoadState; import lua.value.LString; public class DebugUtils { - public static final boolean IS_DEBUG = false; + public static final boolean IS_DEBUG = true; public static void println(String message) { if (IS_DEBUG) { diff --git a/src/main/java/lua/debug/EnumType.java b/src/main/java/lua/debug/EnumType.java new file mode 100644 index 00000000..6a4343c5 --- /dev/null +++ b/src/main/java/lua/debug/EnumType.java @@ -0,0 +1,63 @@ +/******************************************************************************* +* Copyright (c) 2007 LuaJ. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +******************************************************************************/ +package lua.debug; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +public class EnumType implements Serializable { + private static final long serialVersionUID = -496099911938395074L; + + protected String name; + protected int ordinal; + protected static Map lookup = new HashMap(); + + public EnumType(String name, int ordinal) { + this.name = name; + this.ordinal = ordinal; + lookup.put(name, this); + } + + public String toString() { + return this.name; + } + + public final boolean equals(Object other) { + return (this == other); + } + + public final int hashCode() { + return System.identityHashCode(this); + } + + public final String name() { + return this.name; + } + + public final int ordinal() { + return this.ordinal; + } +} diff --git a/src/main/java/lua/debug/StackFrame.java b/src/main/java/lua/debug/StackFrame.java index 694e726d..56470fe9 100644 --- a/src/main/java/lua/debug/StackFrame.java +++ b/src/main/java/lua/debug/StackFrame.java @@ -70,7 +70,6 @@ public class StackFrame implements Serializable { /* (non-Javadoc) * @see java.lang.Object#toString() */ - @Override public String toString() { return getSource() + ":" + getLineNumber(); } diff --git a/src/main/java/lua/debug/StandardLuaJVM.java b/src/main/java/lua/debug/StandardLuaJVM.java new file mode 100644 index 00000000..01a8a5e9 --- /dev/null +++ b/src/main/java/lua/debug/StandardLuaJVM.java @@ -0,0 +1,305 @@ +/******************************************************************************* +* Copyright (c) 2007 LuaJ. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +******************************************************************************/ +package lua.debug; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.Timer; +import java.util.TimerTask; + +import lua.GlobalState; +import lua.StackState; +import lua.addon.luacompat.LuaCompat; +import lua.addon.luajava.LuaJava; +import lua.io.Closure; +import lua.io.LoadState; +import lua.io.Proto; +import lua.value.LString; +import lua.value.LValue; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.GnuParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.OptionBuilder; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; + +/** + * StandardLuaJVM executes a lua program in normal run mode or debug mode. + * + * @author: Shu Lei + * @version: 1.0 + */ +public class StandardLuaJVM implements DebugRequestListener { + protected Options options = new Options(); + protected boolean isDebugMode = false; + protected DebugSupport debugSupport; + protected int requestPort; + protected int eventPort; + protected String script; + protected String[] scriptArgs; + protected StackState state; + protected boolean isReady = false; + protected boolean isTerminated = false; + + public StandardLuaJVM() { + options.addOption(OptionBuilder.withArgName("requestPort eventPort"). + hasArgs(2). + isRequired(false). + withValueSeparator(' '). + withDescription("run LuaJ VM in debug mode"). + create("debug")); + options.addOption(OptionBuilder.withArgName("LuaJProgram"). + withDescription("lua program to be executed"). + isRequired(). + hasArgs(). + withValueSeparator(' '). + create("file")); + } + + protected void printUsage() { + HelpFormatter formatter = new HelpFormatter(); + formatter.printHelp("java StandardLuaJVM", options); + } + + protected void parse(String[] args) throws ParseException { + CommandLineParser parser = new GnuParser(); + try { + CommandLine line = parser.parse(options, args); + if (line.hasOption("debug")) { + this.isDebugMode = true; + String[] ports = line.getOptionValues("debug"); + + this.requestPort = Integer.parseInt(ports[0]); + if (this.requestPort <= 0) { + throw new ParseException("Invalid request port: it must be greater than zero."); + } + + this.eventPort = Integer.parseInt(ports[1]); + if (this.eventPort <= 0) { + throw new ParseException("Invalid event port: it must be greater than zero."); + } + + if (this.requestPort == this.eventPort) { + throw new ParseException("Invalid ports: request port and event port must be different"); + } + } + + if (line.hasOption("file")) { + String[] fileArgs = line.getOptionValues("file"); + this.script = URLDecoder.decode(fileArgs[0], "UTF-8"); + DebugUtils.println("Lua script to run: " + this.script); + this.scriptArgs = new String[fileArgs.length - 1]; + for (int i = 1; i < fileArgs.length; i++) { + this.scriptArgs[i-1] = URLDecoder.decode(fileArgs[i], "UTF-8"); + } + } + } catch(NumberFormatException e) { + throw new ParseException("Invalid port number: " + e.getMessage()); + } catch (UnsupportedEncodingException e) { + throw new ParseException("Malformed program argument strings: " + e.getMessage()); + } + } + + protected boolean isDebug() { + return this.isDebugMode; + } + + protected int getRequestPort() { + return this.requestPort; + } + + protected int getEventPort() { + return this.eventPort; + } + + protected String getScript() { + return this.script; + } + + protected boolean hasScriptArgs() { + return (this.scriptArgs != null && this.scriptArgs.length > 0); + } + + protected String[] getScriptArgs() { + return this.scriptArgs; + } + + public void run() throws IOException { + if (isDebug()) { + doDebug(); + } else { + doRun(); + } + } + + protected void init() { + //Reset the _G table + GlobalState.resetGlobals(); + + // add LuaJava bindings + LuaJava.install(); + + // add LuaCompat bindings + LuaCompat.install(); + } + + public void doRun() throws IOException { + init(); + + // new lua state + state = new StackState(); + + // convert args to lua + int numOfScriptArgs = getScriptArgs().length; + LValue[] vargs = new LValue[numOfScriptArgs]; + for (int i = 0; i < numOfScriptArgs; i++) { + vargs[i] = new LString(getScriptArgs()[i]); + } + + // load the Lua file + DebugUtils.println("loading Lua script '" + getScript() + "'"); + InputStream is = new FileInputStream(new File(getScript())); + Proto p = LoadState.undump(state, is, getScript()); + + // create closure and execute + Closure c = new Closure(state, p); + state.doCall(c, vargs); + } + + private void doDebug() throws IOException { + DebugUtils.println("start debugging..."); + this.debugSupport = new DebugSupport(this, getRequestPort(), getEventPort()); + DebugUtils.println("created client request socket connection..."); + debugSupport.start(); + + DebugUtils.println("setting up LuaJava and debug stack state..."); + + init(); + + // new lua state + state = new DebugStackState(); + getDebugState().addDebugEventListener(debugSupport); + + // load the Lua file + DebugUtils.println("loading Lua script '" + getScript() + "'"); + InputStream is = new FileInputStream(new File(getScript())); + Proto p = LoadState.undump(state, is, getScript()); + + // create closure and execute + final Closure c = new Closure(state, p); + getDebugState().suspend(); + + new Thread(new Runnable() { + public void run() { + int numOfScriptArgs = getScriptArgs().length; + LValue[] vargs = new LValue[numOfScriptArgs]; + for (int i = 0; i < numOfScriptArgs; i++) { + vargs[i] = new LString(getScriptArgs()[i]); + } + + getDebugState().doCall(c, vargs); + stop(); + } + }).start(); + + debugSupport.fireEvent(new DebugEvent(DebugEventType.started)); + } + + private DebugStackState getDebugState() { + return (DebugStackState)state; + } + + /* (non-Javadoc) + * @see lua.debug.DebugRequestListener#handleRequest(java.lang.String) + */ + public DebugResponse handleRequest(DebugRequest request) { + if (!isDebug()) { + throw new UnsupportedOperationException("Must be in debug mode to handle the debug requests"); + } + + DebugUtils.println("handling request: " + request.toString()); + DebugRequestType requestType = request.getType(); + if (DebugRequestType.suspend == requestType) { + DebugResponse status = getDebugState().handleRequest(request); + DebugEvent event = new DebugEvent(DebugEventType.suspendedByClient); + debugSupport.fireEvent(event); + return status; + } else if (DebugRequestType.resume == requestType) { + DebugResponse status = getDebugState().handleRequest(request); + DebugEvent event = new DebugEvent(DebugEventType.resumedByClient); + debugSupport.fireEvent(event); + return status; + } else if (DebugRequestType.exit == requestType) { + stop(); + return DebugResponseSimple.SUCCESS; + } else { + return getDebugState().handleRequest(request); + } + } + + protected void stop() { + DebugUtils.println("exit LuaJ VM..."); + if (this.debugSupport != null) { + DebugEvent event = new DebugEvent(DebugEventType.terminated); + debugSupport.fireEvent(event); + Timer timer = new Timer("DebugServerDeathThread"); + timer.schedule(new TimerTask() { + public void run() { + debugSupport.stop(); + debugSupport = null; + } + }, 500); + } + getDebugState().exit(); + } + + /** + * Parses the command line arguments and executes/debugs the lua program. + * @param args -- command line arguments: + * [-debug requestPort eventPort] -file luaProgram args + * @throws IOException + */ + public static void main(String[] args) { + StandardLuaJVM vm = new StandardLuaJVM(); + + try { + vm.parse(args); + } catch (ParseException e) { + DebugUtils.println(e.getMessage()); + vm.printUsage(); + return; + } + + try { + vm.run(); + } catch (IOException e) { + //TODO: handle the error + e.printStackTrace(); + } + } +} diff --git a/src/main/java/lua/debug/Variable.java b/src/main/java/lua/debug/Variable.java index a4bedd29..65976baa 100644 --- a/src/main/java/lua/debug/Variable.java +++ b/src/main/java/lua/debug/Variable.java @@ -56,10 +56,6 @@ public class Variable implements Serializable { return this.index; } - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override public String toString() { return "index: " + getIndex() + " name:" + getName() + " type: " + Lua.TYPE_NAMES[getType()] + " value:" + getValue(); } diff --git a/src/test/java/lua/debug/LuaJVMTest.java b/src/test/java/lua/debug/LuaJVMTest.java index 7dc186d4..01a4a9bd 100644 --- a/src/test/java/lua/debug/LuaJVMTest.java +++ b/src/test/java/lua/debug/LuaJVMTest.java @@ -24,10 +24,9 @@ package lua.debug; import java.net.URL; import junit.framework.TestCase; -import lua.LuaJVM; /** - * Sanity test for LuaJVM. + * Sanity test for StandardLuaJVM. */ public class LuaJVMTest extends TestCase { protected void doTestRun(String testName) { @@ -37,7 +36,7 @@ public class LuaJVMTest extends TestCase { if (filePath != null) { args[1] = filePath.getPath(); try { - LuaJVM.main(args); + StandardLuaJVM.main(args); } catch (Exception e) { e.printStackTrace(); fail("Test " + testName + " failed due to " + e.getMessage()); @@ -70,7 +69,8 @@ public class LuaJVMTest extends TestCase { //"strlib" }; - for (String test : tests) { + for (int i = 0; i < tests.length; i++) { + String test = tests[i]; System.out.println("==> running test: " + test + ".lua"); doTestRun(test + ".lua"); System.out.println("==> running test: " + test + ".luac");