diff --git a/build.mod b/build.mod new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/build.mod @@ -0,0 +1 @@ + diff --git a/debugger/CommandLineController.hx b/debugger/CommandLineController.hx index 643cbd5..d3c4a9d 100644 --- a/debugger/CommandLineController.hx +++ b/debugger/CommandLineController.hx @@ -8,7 +8,7 @@ * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -34,8 +34,42 @@ class CommandLineController implements IController * Creates a new command line interface. This interface will read and * parse Commands from stdin, and emit debugger output to stdout. **/ + + /** + * Variables and methods to keep track of program-wide data of interest. + * current_file tracks the current file being stepped through. This is + * to allow the user to issue a break command without stating the file + * should they so desire. + *prompt_lock_status functions as a semaphore for the prompt. This is to + *fix a bug in which the prompt would print before the final debugger + *statement. To fix this, a mechanism was added that allows the prompt + * to be locked directly after printing, and then unlocked at the completion + * of the command. Only when prompt_status is set to true can the prompt + * print. Should an unlock fail, a timeout of one second is present. + **/ + + private var current_file = ""; + private var prompt_lock_status = false; + + private function promptUnlock() { + //untyped __global__.__hxcpp_dbg_setPrintReady(true); + prompt_lock_status = true; + } + + private function promptLock() { + //untyped __global__.__hxcpp_dbg_setPrintReady(false); + prompt_lock_status = false; + } + + private function promptLockStatus() { + //return untyped __global__.__hxcpp_dbg_getPrintReady(); + return prompt_lock_status; + } + public function new() { + untyped __global__.__hxcpp_dbg_setPrint(true); + promptLock(); Sys.println(""); Sys.println("-=- hxcpp built-in debugger in command line mode -=-"); Sys.println("-=- Use 'help' for help if you need it. -=-"); @@ -48,6 +82,7 @@ class CommandLineController implements IController // Command 0 is not valid mStoredCommands.push(""); this.setupRegexHandlers(); + promptLock(); } // Called when the process being debugged has started again @@ -67,20 +102,40 @@ class CommandLineController implements IController public function getNextCommand() : Command { var carriedCommandLine : String = ""; - + var timeOut = 1000; while (true) { var input = mInputs[mInputs.length - 1]; + var time = Date.now().getTime(); + //Change symbol if in unsafe mode + var promptSymbol = " $ "; + if(mUnsafeMode) { + promptSymbol = " # "; + } if (mInputs.length == 1) { - Sys.print("\n" + mStoredCommands.length + "> " + - carriedCommandLine); + while(true) { + //If a flag fails to be raised, print a prompt anyway after + //one second (defined in timeOut as 1000) + var timeNow = Date.now().getTime(); + var delta = timeNow - time; + if(promptLockStatus() || (delta > timeOut)) { + Sys.print("\n" + mStoredCommands.length + ":" + " [" + current_file + "]" + promptSymbol + + "> " + carriedCommandLine); + promptLock(); + break; + } + } } var commandLine = null; try { - commandLine = StringTools.trim(carriedCommandLine + - input.readLine()); + var commandLineInput = input.readLine(); + if(commandLineInput == "") { + promptUnlock(); + } + commandLine = StringTools.trim(carriedCommandLine + + commandLineInput); carriedCommandLine = ""; } catch (e : haxe.io.Eof) { @@ -94,19 +149,20 @@ class CommandLineController implements IController continue; } } - if (mInputs.length == 1) { Sys.println(""); + //promptUnlock(); } // If the command line ends with "\", don't execute the command, // just append it to the carriedCommandLine. This is to assist // when program or thread event output has confused the user and // they wish to continue the command in progress. - + if (StringTools.endsWith(commandLine, "\\")) { - carriedCommandLine = + carriedCommandLine = commandLine.substr(0, commandLine.length - 1); + promptUnlock(); continue; } @@ -148,7 +204,7 @@ class CommandLineController implements IController // If it's a bang command, replace it with the stored command if (charZero == "!") { - var number = + var number = Std.parseInt(StringTools.trim(commandLine.substr(1))); if ((number <= 0) || (number >= mStoredCommands.length)) { Sys.println("No command " + number + " in history."); @@ -176,6 +232,7 @@ class CommandLineController implements IController if (!matched) { Sys.println("Invalid command."); + promptUnlock(); continue; } @@ -185,6 +242,7 @@ class CommandLineController implements IController mLastCommand = command; return command; } + } } @@ -198,89 +256,111 @@ class CommandLineController implements IController switch (message) { case ErrorInternal(details): Sys.println("Debugged thread reported internal error: " + details); + promptUnlock(); case ErrorNoSuchThread(number): Sys.println("No such thread " + number + "."); + promptUnlock(); case ErrorNoSuchFile(fileName): Sys.println("No such file " + fileName + "."); + promptUnlock(); case ErrorNoSuchBreakpoint(number): Sys.println("No such breakpoint " + number + "."); + promptUnlock(); case ErrorBadClassNameRegex(details): Sys.println("Invalid class name regular expression: " + details + "."); + promptUnlock(); case ErrorBadFunctionNameRegex(details): Sys.println("Invalid function name regular expression: " + details + "."); + promptUnlock(); case ErrorNoMatchingFunctions(className, functionName, unresolvableClasses): - Sys.println("No functions matching " + className + "." + + Sys.println("No functions matching " + className + "." + functionName + "."); printUnresolvableClasses(unresolvableClasses); + promptUnlock(); case ErrorBadCount(count): Sys.println("Bad count " + count + "."); + promptUnlock(); case ErrorCurrentThreadNotStopped(threadNumber): Sys.println("Current thread " + threadNumber + " not stopped."); + promptUnlock(); case ErrorEvaluatingExpression(details): Sys.println("Failed to evaluate expression: " + details); + promptUnlock(); case OK: // This message is just sent as a way to say that commands that // don't have any status were received - + case Exited: Sys.println("Debugged process has exited."); + promptUnlock(); case Detached: Sys.println("Debugged process has detached."); - + promptUnlock(); + case Files(list): printStringList(list, "\n"); Sys.println(""); + promptUnlock(); case AllClasses(list): printStringList(list, "\n"); Sys.println(""); - + promptUnlock(); + case Classes(list): // The command line controller never issues a request that should // have a Classes response, instead it asks for AllClasses throw "Internal error: unexpected Classes"; + promptUnlock(); case MemBytes(bytes): Sys.println(bytes + " bytes used."); + promptUnlock(); case Compacted(bytesBefore, bytesAfter): Sys.println(bytesBefore + " bytes used before compaction."); Sys.println(bytesAfter + " bytes used after compaction."); + promptUnlock(); case Collected(bytesBefore, bytesAfter): Sys.println(bytesBefore + " bytes used before collection."); Sys.println(bytesAfter + " bytes used after collection."); + promptUnlock(); case ThreadLocation(number, frameNumber, className, functionName, - fileName, lineNumber): + fileName, lineNumber, columnNumber): Sys.println("* " + frameNumber + " : " + className + "." + functionName + "() at " + - fileName + ":" + lineNumber); - + fileName + ":" + lineNumber + ":" + columnNumber); + promptUnlock(); + case FileLineBreakpointNumber(number): Sys.println("Breakpoint " + number + " set and enabled."); + promptUnlock(); case ClassFunctionBreakpointNumber(number, unresolvableClasses): Sys.println("Breakpoint " + number + " set and enabled."); printUnresolvableClasses(unresolvableClasses); - + promptUnlock(); + case Breakpoints(Terminator): Sys.println("No breakpoints."); - + promptUnlock(); + case Breakpoints(list): Sys.println("Number | E/d | M | Description"); while (true) { @@ -288,16 +368,18 @@ class CommandLineController implements IController case Terminator: break; case Breakpoint(number, description, enabled, multi, next): - Sys.println(padString(Std.string(number), 9) + + Sys.println(padString(Std.string(number), 9) + (enabled ? "E " : " d ") + (multi ? "* " : " ") + description); list = next; } } + promptUnlock(); case BreakpointDescription(number, Terminator): Sys.println("Breakpoint " + number + ":"); Sys.println(" Breaks nowhere!"); + promptUnlock(); case BreakpointDescription(number, list): Sys.println("Breakpoint " + number + ":"); @@ -305,9 +387,13 @@ class CommandLineController implements IController switch (list) { case Terminator: break; - case FileLine(fileName, lineNumber, next): - Sys.println(" Breaks at " + fileName + ":" + - lineNumber + "."); + case FileLine(fileName, lineNumber, columnNumber, next): + var desc = " Breaks at " + fileName + ":" + lineNumber; + if(columnNumber != -1) { + desc = desc + ":" + columnNumber; + } + desc = desc + "."; + Sys.println(desc); list = next; case ClassFunction(className, functionName, next): Sys.println(" Breaks at " + className + "." + @@ -315,40 +401,50 @@ class CommandLineController implements IController list = next; } } + promptUnlock(); case BreakpointStatuses(Terminator): Sys.println("No breakpoints affected."); - + promptUnlock(); + case BreakpointStatuses(list): while (true) { switch (list) { case Terminator: + promptUnlock(); break; case Nonexistent(number, next): Sys.println("Breakpoint " + number + " does not exist."); + promptUnlock(); list = next; case Disabled(number, next): Sys.println("Breakpoint " + number + " disabled."); + promptUnlock(); list = next; case AlreadyDisabled(number, next): Sys.println("Breakpoint " + number + " was already disabled."); + promptUnlock(); list = next; case Enabled(number, next): Sys.println("Breakpoint " + number + " enabled."); + promptUnlock(); list = next; case AlreadyEnabled(number, next): Sys.println("Breakpoint " + number + " was already enabled."); + promptUnlock(); list = next; case Deleted(number, next): Sys.println("Breakpoint " + number + " deleted."); + promptUnlock(); list = next; } } case ThreadsWhere(Terminator): Sys.println("No threads."); + promptUnlock(); case ThreadsWhere(list): var needNewline : Bool = false; @@ -368,16 +464,21 @@ class CommandLineController implements IController switch (status) { case Running: Sys.println("running)"); + promptUnlock(); list = next; isRunning = true; case StoppedImmediate: Sys.println("stopped):"); + promptUnlock(); case StoppedBreakpoint(number): Sys.println("stopped in breakpoint " + number + "):"); + promptUnlock(); case StoppedUncaughtException: Sys.println("uncaught exception):"); + promptUnlock(); case StoppedCriticalError(description): Sys.println("critical error: " + description + "):"); + promptUnlock(); } var hasStack = false; while (true) { @@ -385,18 +486,20 @@ class CommandLineController implements IController case Terminator: break; case Frame(isCurrent, number, className, functionName, - fileName, lineNumber, next): + fileName, lineNumber, columnNumber, next): Sys.print((isCurrent ? "* " : " ")); Sys.print(padStringRight(Std.string(number), 5)); Sys.print(" : " + className + "." + functionName + "()"); - Sys.println(" at " + fileName + ":" + lineNumber); + Sys.println(" at " + fileName + ":" + lineNumber + ":" + columnNumber); hasStack = true; + promptUnlock(); frameList = next; } } if (!hasStack && !isRunning) { Sys.println("No stack."); + promptUnlock(); } list = next; } @@ -405,30 +508,41 @@ class CommandLineController implements IController case Variables(list): printStringList(list, "\n"); Sys.println(""); - + promptUnlock(); + case Value(expression, type, value): Sys.println(expression + " : " + type + " = " + value); + promptUnlock(); case Structured(structuredValue): throw "Internal error: unexpected Structured"; + promptUnlock(); case ThreadCreated(number): Sys.println("\nThread " + number + " created."); + promptUnlock(); case ThreadTerminated(number): Sys.println("\nThread " + number + " terminated."); + promptUnlock(); case ThreadStarted(number): // Don't print anything case ThreadStopped(number, frameNumber, className, functionName, - fileName, lineNumber): - Sys.println("\nThread " + number + " stopped in " + - className + "." + functionName + "() at " + - fileName + ":" + lineNumber + "."); - } + fileName, lineNumber, columnNumber): + + current_file = fileName; + + if(untyped __global__.__hxcpp_dbg_getPrint()) { + Sys.println("\nThread " + number + " stopped in " + + className + "." + functionName + "() at " + + fileName + ":" + lineNumber + ":" + columnNumber + "."); + promptUnlock(); + } + } } - + private function exit(regex : EReg) : Null { Sys.println("Exiting."); @@ -438,6 +552,7 @@ class CommandLineController implements IController private function detach(regex : EReg) : Null { + promptUnlock(); return Detach; } @@ -456,12 +571,14 @@ class CommandLineController implements IController for (h in gHelp) { if (h.c == cmd) { Sys.println( h.l + "\n"); + promptUnlock(); return null; } } Sys.println("No such command '" + cmd + "'"); } + promptUnlock(); return null; } @@ -470,6 +587,7 @@ class CommandLineController implements IController var line = regex.matched(1); if (line.length == 0) { Sys.println("The source command requires one argument."); + promptUnlock(); return null; } if (gRegexQuotes.match(line)) { @@ -481,7 +599,7 @@ class CommandLineController implements IController else { Sys.println("Failed to parse source line at: " + line + "."); } - + promptUnlock(); return null; } @@ -494,13 +612,14 @@ class CommandLineController implements IController catch (e : Dynamic) { Sys.println("Failed to open " + path + " for sourcing."); } - + promptUnlock(); return null; } private function history(regex : EReg) : Null { this.historyRange(1, mStoredCommands.length - 1); + promptUnlock(); return null; } @@ -508,19 +627,22 @@ class CommandLineController implements IController { var number = Std.parseInt(regex.matched(1)); this.historyRange(number, number); + promptUnlock(); return null; } private function history_upto(regex : EReg) : Null { this.historyRange(1, Std.parseInt(regex.matched(1))); + promptUnlock(); return null; } private function history_from(regex : EReg) : Null { - this.historyRange(Std.parseInt(regex.matched(1)), + this.historyRange(Std.parseInt(regex.matched(1)), mStoredCommands.length - 1); + promptUnlock(); return null; } @@ -528,6 +650,7 @@ class CommandLineController implements IController { this.historyRange(Std.parseInt(regex.matched(1)), Std.parseInt(regex.matched(2))); + promptUnlock(); return null; } @@ -544,6 +667,7 @@ class CommandLineController implements IController for (i in first ... (last + 1)) { Sys.println("(" + i + ") " + mStoredCommands[i]); } + promptUnlock(); } private function files(regex : EReg) : Null @@ -590,7 +714,7 @@ class CommandLineController implements IController mUnsafeMode = true; Sys.println("Now in unsafe mode."); } - + promptUnlock(); return null; } @@ -604,18 +728,37 @@ class CommandLineController implements IController Sys.println("Already in safe mode."); } + promptUnlock(); return null; } private function break_now(regex : EReg) : Null { - return BreakNow; + var res = BreakNow; + promptUnlock(); + return res; + } + //CS116 - changed 0 to 1 + private function break_file_line_col(regex : EReg) : Null + { + return AddFileLineBreakpoint(regex.matched(2), + Std.parseInt(regex.matched(3)), Std.parseInt(regex.matched(4))); + } + + private function break_file_line_col_current(regex: EReg) : Null { + return AddFileLineBreakpoint(current_file, Std.parseInt(regex.matched(2)), + Std.parseInt(regex.matched(3))); } private function break_file_line(regex : EReg) : Null { - return AddFileLineBreakpoint(regex.matched(2), - Std.parseInt(regex.matched(3))); + return AddFileLineBreakpoint(regex.matched(2), + Std.parseInt(regex.matched(3)), -1); + } + + private function break_file_line_current(regex : EReg) : Null { + return AddFileLineBreakpoint(current_file, + Std.parseInt(regex.matched(2)), -1); } private function break_class_function(regex : EReg) : Null @@ -639,6 +782,7 @@ class CommandLineController implements IController if (index == -1) { Sys.println("Invalid command."); + promptUnlock(); return null; } @@ -655,13 +799,14 @@ class CommandLineController implements IController if (index == -1) { Sys.println("Invalid command."); + promptUnlock(); return null; } var className = value.substr(0, index + 1); value = value.substr(index + 1); - + var regex = ~/[\s]*\.[\s]*([a-zA-Z_][a-zA-Z0-9_]*)[\s]*$/; if (regex.match(value)) { return AddClassFunctionBreakpoint(className, regex.matched(1)); @@ -676,6 +821,7 @@ class CommandLineController implements IController if (index == -1) { Sys.println("Invalid command."); + promptUnlock(); return null; } @@ -684,6 +830,7 @@ class CommandLineController implements IController } else { Sys.println("Invalid command."); + promptUnlock(); return null; } } @@ -762,7 +909,7 @@ class CommandLineController implements IController private function clear_file_line(regex : EReg) : Null { return DeleteFileLineBreakpoint(regex.matched(1), - Std.parseInt(regex.matched(2))); + Std.parseInt(regex.matched(2)), 0); } private function continue_current(regex : EReg) : Null @@ -787,6 +934,11 @@ class CommandLineController implements IController Std.parseInt(regex.matched(2)) : 1); } + private function nextLine_execution(regex : EReg) : Null { + return NextLine((regex.matched(2).length > 0) ? + Std.parseInt(regex.matched(2)) : 1); + } + private function finish_execution(regex : EReg) : Null { return Finish((regex.matched(2).length > 0) ? @@ -945,7 +1097,7 @@ class CommandLineController implements IController } index += 1; } - + return -1; } @@ -953,7 +1105,7 @@ class CommandLineController implements IController { while (index < str.length) { var char = str.charAt(index); - if ((char == "/") && + if ((char == "/") && ((index == 0) || (str.charAt(index - 1) != "\\"))) { return index; } @@ -1023,7 +1175,10 @@ class CommandLineController implements IController { r: ~/^unsafe[\s]*$/, h: unsafe }, { r: ~/^safe[\s]*$/, h: safe }, { r: ~/^(b|break)[\s]*$/, h : break_now }, + { r: ~/^(b|break)[\s]+([^:]+):[\s]*([0-9]+):[\s]*([0-9]+)[\s]*$/, h : break_file_line_col }, + { r: ~/^(b|break)[\s][\s]*([0-9]+):[\s]*([0-9]+)[\s]*$/, h : break_file_line_col_current }, { r: ~/^(b|break)[\s]+([^:]+):[\s]*([0-9]+)[\s]*$/, h : break_file_line }, + { r: ~/^(b|break)[\s]+([0-9]+)[\s]*$/, h : break_file_line_current }, { r: ~/^(b|break)[\s]+(([a-zA-Z0-9_]+\.)+[a-zA-Z0-9_]+)[\s]*$/, h : break_class_function }, { r: ~/^(b|break)[\s]+(([a-zA-Z0-9_]+\.)+\/.*)$/, h : break_class_regexp }, { r: ~/^(b|break)[\s]+(\/.*)$/, h : break_possible_regexps }, @@ -1052,6 +1207,8 @@ class CommandLineController implements IController { r: ~/^(step|stepi|s)()[\s]*$/, h: step_execution }, { r: ~/^(step|stepi|s)([\s]+[0-9]+)[\s]*$/, h: step_execution }, { r: ~/^(next|nexti|n)()[\s]*$/, h: next_execution }, + { r: ~/^(nextLine|nextl|nl)()[\s]*$/, h: nextLine_execution }, + { r: ~/^(nextLine|nextl|nl)([\s]+[0-9]+)[\s]*$/, h: nextLine_execution }, { r: ~/^(next|nexti|n)([\s]+[0-9]+)[\s]*$/, h: next_execution }, { r: ~/^(finish|f)()[\s]*$/, h: finish_execution }, { r: ~/^(finish|f)([\s]+[0-9]+)[\s]*$/, h: finish_execution }, @@ -1163,8 +1320,8 @@ class CommandLineController implements IController l : "Syntax: mem\n\n" + "The mem command displays the amount of bytes currently used by the\n" + "debugged process." }, - - { c : "compact", s : "Compacts the heap", + + { c : "compact", s : "Compacts the heap", l : "Syntax: compact\n\n" + "The compact command compacts the program's heap as much as possible\n" + "and prints out the number of bytes used by the program before and\n" + @@ -1203,11 +1360,11 @@ class CommandLineController implements IController "printed or modified. To leave safe mode, use the 'unsafe' command." }, { c : "break", s : "Sets a breakpoint", - l : "Syntax: break :/.\n\n" + + l : "Syntax: break :/::/.\n\n" + "The break (or b) command sets a breakpoint. Breakpoints take effect\n" + "immediately and all threads will break on all breakpoints whenever\n" + "the breakpoint is hit.\n" + - "Breakpoints may be specified either by file and line number, or by\n" + + "Breakpoints may be specified either by file and line (/column) number, or by\n" + "class name and function name.\n" + "In the class.function case, the class name, or function name or\n" + "both, may optionally be a regular expression which will cause the\n" + @@ -1217,6 +1374,11 @@ class CommandLineController implements IController "be set can be printed using the 'classes' command.\n\nExamples:\n\n" + " b Foo.hx:10\n" + " Sets a breakpoint in file Foo.hx line 10.\n\n" + + " b Foo.hx:10:5\n" + + "Sets a breakpoint on line ten column 5 of the current file.\n\n" + + " Sets a breakpoint in file Foo.hx line 10, column 5.\n\n" + + " b 10:5\n" + + "Sets a breakpoint on line ten column 5 of the current file.\n\n" + " b SomeClass.SomeFunction\n " + " Sets a breakpoint on entry to the function " + "SomeClass.SomeFunction.\n\n" + @@ -1226,8 +1388,8 @@ class CommandLineController implements IController " b /.*/.new\n" + " Sets a breakpoint on entry to the constructor of every class.\n\n" + " b /.*/./.*/\n" + - " Sets a breakpoint on entry to every function of every class." }, - + " Sets a breakpoint on entry to every function of every class." }, + { c : "list", s : "Lists breakpoints", l : "Syntax: list/l [all/enabled/en/disabled/dis] breakpoints/b\n\n" + "The list (or l) command lists all breakpoints that match the given\n" + @@ -1318,14 +1480,19 @@ class CommandLineController implements IController { c : "next", s : "Single steps a thread in current frame", l : "Syntax: next/n [N]\n\n" + "The next (or n) command steps the current thread over a function\n" + - "call. If the next line of Haxe code to execute is a function call,\n" + + "call. If the next expression to execute is a function call,\n" + "the entire function is executed and the thread stops before\n" + - "executing the line of code after the function call. If the next line\n" + + "executing the expression after the function call. If the next line\n" + "of Haxe code is not a function, the next command behaves exactly like\n" + "the step command. The optional parameter N specifies how many\n" + "function calls or Haxe lines of code to step. If not provided, the\n" + " default is 1." }, + { c : "nextLine", s : "Steps a thread to a new line.", +l : "Syntax: nextLine/nl/nextl [lines]\n\n" + + "Steps through a thread until a new is reached. If a number is\n" + + "specified, then execution will advance by that number of lines." }, + { c : "finish", s : "Continues until return from frame", l : "Syntax: finish/f [N]\n\n" + "The finish (or f) command causes the current thread to finish\n" + @@ -1424,7 +1591,7 @@ class CommandLineController implements IController " $.baz : Array[4] = [ 1, 2, 3, 4 ]\n" + " $.foo : Int = 1\n\n" + " 9> set someValue.arr = $.baz\n\n" + - " someValue.arr : Array[4] = [ 1, 2, 3, 4 ]" } + " someValue.arr : Array[4] = [ 1, 2, 3, 4 ]" } ]; } diff --git a/debugger/DebuggerThread.hx b/debugger/DebuggerThread.hx index 9263293..b943138 100644 --- a/debugger/DebuggerThread.hx +++ b/debugger/DebuggerThread.hx @@ -177,8 +177,8 @@ class DebuggerThread case SetCurrentThread(number): emit(this.setCurrentThread(number)); - case AddFileLineBreakpoint(fileName, lineNumber): - emit(this.addFileLineBreakpoint(fileName, lineNumber)); + case AddFileLineBreakpoint(fileName, lineNumber, columnNumber): + emit(this.addFileLineBreakpoint(fileName, lineNumber, columnNumber)); case AddClassFunctionBreakpoint(className, functionName): emit(this.addClassFunctionBreakpoint @@ -208,8 +208,8 @@ class DebuggerThread case DeleteBreakpointRange(first, last): emit(this.deleteBreakpointRange(first, last)); - case DeleteFileLineBreakpoint(fileName, lineNumber): - emit(this.deleteFileLineBreakpoint(fileName, lineNumber)); + case DeleteFileLineBreakpoint(fileName, lineNumber, columnNumber): + emit(this.deleteFileLineBreakpoint(fileName, lineNumber, columnNumber)); case BreakNow: emit(this.breakNow()); @@ -223,6 +223,9 @@ class DebuggerThread case Next(count): emit(this.next(count)); + case NextLine(count): + emit(this.nextLine(count)); + case Finish(count): emit(this.finish(count)); @@ -279,7 +282,9 @@ class DebuggerThread stackFrame : Int, className : String, functionName : String, - fileName : String, lineNumber : Int) + fileName : String, + lineNumber : Int, columnNumber: Int + ) { switch (event) { case Debugger.THREAD_CREATED: @@ -305,7 +310,8 @@ class DebuggerThread } mStateMutex.release(); emit(ThreadStopped(threadNumber, stackFrame, className, - functionName, fileName, lineNumber)); + functionName, fileName, lineNumber, columnNumber)); + } } @@ -363,7 +369,7 @@ class DebuggerThread var initial_to_skip = to_skip; var total = 0; var byte_total = 0; - + // Accumulate classes to show var classes_to_use = new Array(); @@ -389,7 +395,7 @@ class DebuggerThread return Reflect.compare(b, a); }); - var list : ClassList = ((continuation == null) ? + var list : ClassList = ((continuation == null) ? Terminator : Continued(continuation)); for (f in classes_to_use) { @@ -455,7 +461,7 @@ class DebuggerThread var frame = ti.stack[frameNumber]; return ThreadLocation(number, frameNumber, frame.className, frame.functionName, frame.fileName, - frame.lineNumber); + frame.lineNumber, frame.columnNumber); } } @@ -463,9 +469,13 @@ class DebuggerThread } private function addFileLineBreakpoint(fileName : String, - lineNumber : Int) : Message + lineNumber : Int, columnNumber : Int) : Message { + var desc = (fileName + ":" + lineNumber); + if(columnNumber != -1) { + desc = desc + ":" + columnNumber; + } if (!mBreakpointsByDescription.exists(desc)) { var files = Debugger.getFiles(); @@ -475,7 +485,7 @@ class DebuggerThread new Breakpoint(mNextBreakpointNumber++, desc); mBreakpoints.set(breakpoint.number, breakpoint); mBreakpointsByDescription.set(desc, breakpoint); - breakpoint.addFileLine(fileName, lineNumber); + breakpoint.addFileLine(fileName, lineNumber, columnNumber); break; } } @@ -657,9 +667,9 @@ class DebuggerThread for (b in breakpoint.bps()) { switch (b) { - case BP.FileLine(bp, fileName, lineNumber): + case BP.FileLine(bp, fileName, lineNumber, columnNumber): list = BreakpointLocationList.FileLine - (fileName, lineNumber, list); + (fileName, lineNumber, columnNumber, list); case BP.ClassFunction(bp, className, functionName): list = BreakpointLocationList.ClassFunction (className, functionName, list); @@ -734,7 +744,7 @@ class DebuggerThread } private function deleteFileLineBreakpoint(fileName : String, - lineNumber : Int) : Message + lineNumber : Int, columnNumber: Int) : Message { var list : BreakpointStatusList = Terminator; @@ -798,6 +808,10 @@ class DebuggerThread return this.stepExecution(count, Debugger.STEP_OVER); } + private function nextLine(count) : Message { + return this.stepExecutionLine(count, Debugger.STEP_OVER); + } + private function finish(count) : Message { return this.stepExecution(count, Debugger.STEP_OUT); @@ -855,7 +869,7 @@ class DebuggerThread list = Frame(((threadInfo.number == mCurrentThreadNumber) && (frameNumber == mCurrentStackFrame)), frameNumber, sf.className, sf.functionName, - sf.fileName, sf.lineNumber, list); + sf.fileName, sf.lineNumber, sf.columnNumber, list); frameNumber += 1; } } @@ -908,7 +922,7 @@ class DebuggerThread return ThreadLocation(mCurrentThreadNumber, mCurrentStackFrame, frame.className, frame.functionName, - frame.fileName, frame.lineNumber); + frame.fileName, frame.lineNumber, frame.columnNumber); } private function down(count : Int) : Message @@ -941,7 +955,7 @@ class DebuggerThread return ThreadLocation(mCurrentThreadNumber, mCurrentStackFrame, frame.className, frame.functionName, - frame.fileName, frame.lineNumber); + frame.fileName, frame.lineNumber, frame.columnNumber); } private function setFrame(number : Int) : Message @@ -972,10 +986,9 @@ class DebuggerThread mStateMutex.release(); var frame = threadInfo.stack[mCurrentStackFrame]; - return ThreadLocation(mCurrentThreadNumber, mCurrentStackFrame, frame.className, frame.functionName, - frame.fileName, frame.lineNumber); + frame.fileName, frame.lineNumber, frame.columnNumber); } private function variables(unsafe : Bool) : Message @@ -1081,11 +1094,11 @@ class DebuggerThread } } } - + private function getStructured(unsafe : Bool, expression : String) : Message { mStateMutex.acquire(); - + // Just to ensure that the current stack frame is known this.getCurrentThreadInfoLocked(); @@ -1143,10 +1156,20 @@ class DebuggerThread } Debugger.stepThread(mCurrentThreadNumber, type, count); - + return OK; } + private function stepExecutionLine(count : Int, type : Int) : Message { + if (count < 1) { + return ErrorBadCount(count); + } + + Debugger.stepThreadLine(mCurrentThreadNumber, type, count); + + return OK; + } + // Find by a debugger breakpoint number given the breakpoint field of a // ThreadInfo private function findBreakpoint(bpNumber : Int) : Int @@ -1154,7 +1177,7 @@ class DebuggerThread for (breakpoint in mBreakpoints) { for (bp in breakpoint.bps()) { switch (bp) { - case FileLine(bp, fileName, lineNumber): + case FileLine(bp, fileName, lineNumber, columnNumber): if (bp == bpNumber) { return breakpoint.number; } @@ -1300,7 +1323,7 @@ private class TypeHelpers ret += "\n"; } return ret + indent + "}"; - + case TClass(Array): var arr : Array = cast value; if (arr.length == 0) { @@ -1542,12 +1565,12 @@ private class TypeHelpers if (elideArraysAndObjects) { return Elided(getStructuredValueType(value), expression); } - return List(Anonymous, + return List(Anonymous, getStructuredValueList(value, expression)); case TClass(String): return Single(TypeClass("String"), Std.string(value)); - + case TClass(Array): if (elideArraysAndObjects) { return Elided(TypeArray, expression); @@ -1687,7 +1710,7 @@ private class DebuggerVariables private enum BP { - FileLine(bp : Int, fileName : String, lineNumber : Int); + FileLine(bp : Int, fileName : String, lineNumber : Int, columnNumber : Int); ClassFunction(bp : Int, className : String, functionName : String); } @@ -1711,7 +1734,7 @@ private class Breakpoint { for (b in mBps) { switch (b) { - case BP.FileLine(bp, fileName, lineNumber): + case BP.FileLine(bp, fileName, lineNumber, columnNumber): Debugger.deleteBreakpoint(bp); case BP.ClassFunction(bp, className, functionName): Debugger.deleteBreakpoint(bp); @@ -1719,10 +1742,10 @@ private class Breakpoint } } - public function addFileLine(fileName : String, lineNumber : Int) + public function addFileLine(fileName : String, lineNumber : Int, columnNumber : Int) { mBps.push(BP.FileLine(Debugger.addFileLineBreakpoint - (fileName, lineNumber), fileName, lineNumber)); + (fileName, lineNumber, columnNumber), fileName, lineNumber, columnNumber)); } public function addClassFunction(className : String, functionName : String) @@ -1753,8 +1776,8 @@ private class Breakpoint for (b in oldBps) { switch (b) { - case BP.FileLine(bp, fileName, lineNumber): - this.addFileLine(fileName, lineNumber); + case BP.FileLine(bp, fileName, lineNumber, columnNumber): + this.addFileLine(fileName, lineNumber, columnNumber); case BP.ClassFunction(bp, className, functionName): this.addClassFunction(className, functionName); } @@ -1771,7 +1794,7 @@ private class Breakpoint for (b in mBps) { switch (b) { - case BP.FileLine(bp, fileName, lineNumber): + case BP.FileLine(bp, fileName, lineNumber, columnNumber): Debugger.deleteBreakpoint(bp); case BP.ClassFunction(bp, className, functionName): Debugger.deleteBreakpoint(bp); @@ -2877,4 +2900,4 @@ private class DebugTimer { private var mLogLevel : Int; private var mStartTime : Float; private var mMessage: Dynamic; -} \ No newline at end of file +} diff --git a/debugger/HaxeRemote.hx b/debugger/HaxeRemote.hx index 29e5106..f084cc9 100644 --- a/debugger/HaxeRemote.hx +++ b/debugger/HaxeRemote.hx @@ -8,7 +8,7 @@ * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -177,7 +177,7 @@ class HaxeRemote implements IController private static function LogDebuggerMessage(message : String) { Sys.println("Debugger:" + message); } - + private var mHost : String; private var mPort : Int; private var mSocket : sys.net.Socket; diff --git a/debugger/HaxeServer.hx b/debugger/HaxeServer.hx index ae4d012..d69d2fe 100644 --- a/debugger/HaxeServer.hx +++ b/debugger/HaxeServer.hx @@ -8,7 +8,7 @@ * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -160,6 +160,7 @@ class HaxeServer case ThreadCreated(number): case ThreadTerminated(number): case ThreadStarted(number): + //CS116 case ThreadStopped(number, frameNumber, className, functionName, fileName, lineNumber): default: diff --git a/debugger/IController.hx b/debugger/IController.hx index 3e09137..838c7e3 100644 --- a/debugger/IController.hx +++ b/debugger/IController.hx @@ -8,7 +8,7 @@ * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -34,6 +34,7 @@ interface IController * * @return the next command for the debugger to execute **/ + public function getNextCommand() : Command; /** @@ -84,7 +85,7 @@ enum Command SetCurrentThread(number : Int); // Response: ThreadLocation, OK, ErrorNoSuchThread - AddFileLineBreakpoint(fileName : String, lineNumber : Int); + AddFileLineBreakpoint(fileName : String, lineNumber : Int, columnNumber: Int); // Response: FileLineBreakpointNumber, ErrorNoSuchFile AddClassFunctionBreakpoint(className : String, functionName : String); @@ -115,7 +116,7 @@ enum Command DeleteBreakpointRange(first : Int, last: Int); // Response: BreakpointStatuses - DeleteFileLineBreakpoint(fileName : String, lineNumber : Int); + DeleteFileLineBreakpoint(fileName : String, lineNumber : Int, columnNumber : Int); // Response: BreakpointStatuses BreakNow; @@ -160,6 +161,8 @@ enum Command GetStructured(unsafe : Bool, expression : String); // Response: Structured, ErrorCurrentThreadNotStopped, // ErrorEvaluatingExpression + NextLine(count : Int); + // Response: OK, ErrorCurrentThreadNotStopped, ErrorBadCount } @@ -203,7 +206,7 @@ enum BreakpointList enum BreakpointLocationList { Terminator; - FileLine(fileName : String, lineNumber : Int, + FileLine(fileName : String, lineNumber : Int, columnNumber : Int, next : BreakpointLocationList); ClassFunction(className : String, functionName : String, next : BreakpointLocationList); @@ -246,7 +249,7 @@ enum FrameList { Terminator; Frame(isCurrent : Bool, number : Int, className : String, - functionName : String, fileName : String, lineNumber : Int, + functionName : String, fileName : String, lineNumber : Int, columnNumber : Int, next : FrameList); } @@ -359,10 +362,13 @@ enum Message MemBytes(bytes : Int); Compacted(bytesBefore : Int, bytesAfter : Int); Collected(bytesBefore : Int, bytesAfter : Int); + //cs116 ThreadLocation(number : Int, stackFrame : Int, className : String, - functionName : String, fileName : String, lineNumber : Int); + functionName : String, fileName : String, lineNumber : Int, + columnNumber: Int); + //cs116 FileLineBreakpointNumber(number : Int); - ClassFunctionBreakpointNumber(number : Int, + ClassFunctionBreakpointNumber(number : Int, unresolvableClasses : StringList); Breakpoints(list : BreakpointList); BreakpointDescription(number : Int, list : BreakpointLocationList); @@ -378,5 +384,6 @@ enum Message ThreadStarted(number : Int); ThreadStopped(number : Int, stackFrame : Int, className : String, functionName : String, - fileName : String, lineNumber : Int); + fileName : String, lineNumber : Int, columnNumber: Int); + }