private static void ClearBreakpoints(LispDebugger debugger, string cmd) { if (debugger != null) { string rest = cmd.Substring(5).Trim(); if (rest.Length > 0) { Tuple <bool, int> val = ConvertToInt(rest); if (!val.Item1 || !debugger.ClearBreakpoint(val.Item2)) { debugger.Output.WriteLine("Warning: no breakpoint cleared"); } } else { debugger.Output.WriteLine("Really delete all breakpoints? (y/n)"); string answer; do { answer = debugger.Input.ReadLine(); if (answer != null) { answer = answer.ToUpper(); } } while (!(answer == "Y" || answer == "N" || answer == "YES" || answer == "NO")); if (answer == "Y" || answer == "YES") { debugger.ClearAllBreakpoints(); } } } }
private static void ShowSourceCode(LispDebugger debugger, string sourceCode, string moduleName, int?currentLineNo) { if (debugger != null) { string[] sourceCodeLines = sourceCode.Split('\n'); for (var i = 0; i < sourceCodeLines.Length; i++) { string breakMark = debugger.HasBreakpointAt(i + 1, moduleName) ? "B " : " "; string mark = currentLineNo != null && currentLineNo.Value == i + 1 ? "-->" : string.Empty; debugger.Output.WriteLine("{0,3} {1,2} {2,3} {3}", i + 1, breakMark, mark, sourceCodeLines[i]); } } }
/// <summary> /// Adds a breakpoint. /// Possible command strings after break: /// break 7 --> breakpoint with just one line number in the current module /// break modulename:7 --> breakpoint with line number and module name /// break 7 condition --> breakpoint with line number and condition /// break modulename:7 condition --> breakpoint with line number, module name and condition /// break "modulename with spaces":7 condition --> breakpoint with line number, module name and condition /// </summary> /// <param name="debugger">The debugger.</param> /// <param name="cmd">The command.</param> /// <param name="currentModuleName">Name of the current module.</param> private static void AddBreakpoint(LispDebugger debugger, string cmd, string currentModuleName) { bool added = false; if (debugger != null) { var cmdArgs = new string[0]; string moduleName = currentModuleName; string rest = cmd.Substring(cmd.IndexOf(" ", StringComparison.Ordinal)).Trim(); if (rest.StartsWith("\"")) { // process: filename:linenumber int iStopPos; moduleName = GetStringLiteral(rest.Substring(1), out iStopPos); rest = rest.Substring(iStopPos + 2); // adjust for the two " if (rest.StartsWith(":")) { cmdArgs = rest.Substring(1).Split(' '); } } else { // process: linennumber cmdArgs = rest.Split(' '); } int indexRest = rest.IndexOf(" ", StringComparison.Ordinal); rest = indexRest >= 0 ? rest.Substring(indexRest).Trim() : string.Empty; if (cmdArgs.Length > 0) { string lineNumberString = cmdArgs[0]; int posModuleSeparator = cmdArgs[0].LastIndexOf(":", StringComparison.Ordinal); if (posModuleSeparator >= 0) { lineNumberString = cmdArgs[0].Substring(posModuleSeparator + 1); moduleName = cmdArgs[0].Substring(0, posModuleSeparator); } Tuple <bool, int> val = ConvertToInt(lineNumberString); if (val.Item1) { debugger.AddBreakpoint(val.Item2, moduleName, rest.Length > 0 ? rest : string.Empty); added = true; } } } if (!added && debugger != null) { debugger.Output.WriteLine("Warning: no breakpoint set or modified"); } }
/// <summary> /// Processing of the interactive loop of the debugger. /// </summary> /// <param name="debugger">The debugger.</param> /// <param name="initialTopScope">The initial top scope.</param> /// <param name="startedFromMain">if set to <c>true</c> [started from main].</param> /// <param name="tracing">if set to <c>true</c> tracing is enabled.</param> /// <returns>True if program should be restarted.</returns> /// <exception cref="LispStopDebuggerException"></exception> /// <exception cref="CsLisp.LispStopDebuggerException"></exception> public static bool InteractiveLoop(LispDebugger debugger = null, LispScope initialTopScope = null, bool startedFromMain = false, bool tracing = false) { string interactiveScript = string.Empty; startedFromMain = startedFromMain || debugger == null; if (debugger == null) { debugger = new LispDebugger(); } var globalScope = initialTopScope != null ? initialTopScope.GlobalScope : LispEnvironment.CreateDefaultScope(); // do not switch off tracing if already enabled if (!globalScope.Tracing) { globalScope.Tracing = tracing; } var topScope = initialTopScope != null ? initialTopScope : globalScope; var currentScope = topScope; var bContinueWithNextStatement = false; var bRestart = false; do { debugger.Output.Write(debugger != null ? DbgPrompt : Prompt); // Warning: // QProcess and .NET >3.5 does not work correclty reading from input !!! // see: http://www.qtcentre.org/threads/62415-QProcess-not-communicating-with-net-framework-gt-3-5 // ==> CsLisp is now using .NET 3.5 ! var cmd = debugger.Input.ReadLine(); cmd = cmd != null?cmd.Trim() : null; if (cmd == null || cmd.Equals("exit") || cmd.Equals("quit") || cmd.Equals("q")) { bContinueWithNextStatement = true; bRestart = false; if (!startedFromMain) { throw new LispStopDebuggerException(); } } else if (cmd.Equals("help") || cmd.Equals("h")) { ShowInteractiveCmds(debugger.Output); } else if (cmd.Equals("about")) { LispUtils.ShowAbout(debugger.Output); } else if (cmd.Equals("funcs")) { globalScope.DumpFunctions(); } else if (cmd.Equals("macros")) { globalScope.DumpMacros(); } else if (cmd.Equals("builtins")) { globalScope.DumpBuiltinFunctions(); } else if (cmd.StartsWith("doc")) { var items = cmd.Split(' '); if (items.Length > 1) { string docCmd = "(doc '" + items[1] + ")"; LispVariant result = Lisp.Eval(docCmd, currentScope, currentScope.ModuleName); debugger.Output.WriteLine("{0}", result); } else { globalScope.DumpBuiltinFunctionsHelp(); } } else if (cmd.StartsWith("searchdoc")) { var items = cmd.Split(' '); if (items.Length > 1) { string docCmd = "(searchdoc '" + items[1] + ")"; LispVariant result = Lisp.Eval(docCmd, currentScope, currentScope.ModuleName); debugger.Output.WriteLine("{0}", result); } else { globalScope.DumpBuiltinFunctionsHelp(); } } else if (cmd.Equals("modules")) { globalScope.DumpModules(); } else if (cmd.StartsWith("clear")) { ClearBreakpoints(debugger, cmd); } else if (cmd.Equals("stack") || cmd.StartsWith("k")) { topScope.DumpStack(currentScope.GetCallStackSize()); } else if (cmd.Equals("code") || cmd.StartsWith("c")) { var script = string.Empty; var moduleName = currentScope.ModuleName; if (moduleName == null) { script = interactiveScript; } else { script = moduleName.StartsWith(LispEnvironment.EvalStrTag) ? moduleName.Substring(LispEnvironment.EvalStrTag.Length + moduleName.IndexOf(":", LispEnvironment.EvalStrTag.Length)) : LispUtils.ReadFileOrEmptyString(moduleName); } // use the script given on command line if no valid module name was set if (string.IsNullOrEmpty(script)) { script = debugger.CommandLineScript; } ShowSourceCode(debugger, script, currentScope.ModuleName, currentScope.CurrentLineNo); } else if (cmd.StartsWith("list") || cmd.StartsWith("t")) { debugger.ShowBreakpoints(); } else if (cmd.StartsWith("break ") || cmd.StartsWith("b ")) { AddBreakpoint(debugger, cmd, currentScope.ModuleName); } else if (cmd.Equals("up") || cmd.StartsWith("u")) { if (currentScope.Next != null) { currentScope = currentScope.Next; } } else if (cmd.Equals("down") || cmd.StartsWith("d")) { if (currentScope.Previous != null) { currentScope = currentScope.Previous; } } else if (cmd.Equals("step") || cmd.Equals("s")) { debugger.DoStep(currentScope); bContinueWithNextStatement = true; } else if (cmd.Equals("over") || cmd.Equals("v")) { debugger.DoStepOver(currentScope); bContinueWithNextStatement = true; } else if (cmd.Equals("out") || cmd.Equals("o")) { debugger.DoStepOut(currentScope); bContinueWithNextStatement = true; } else if (cmd.Equals("run") || cmd.Equals("r")) { debugger.DoRun(); bContinueWithNextStatement = true; } else if (cmd.Equals("locals") || cmd.StartsWith("l")) { currentScope.DumpVars(); } else if (cmd.Equals("globals") || cmd.StartsWith("g")) { globalScope.DumpVars(); } else if (cmd.Equals("restart")) { bContinueWithNextStatement = true; bRestart = true; } else if (cmd.Equals("version") || cmd.Equals("ver")) { LispUtils.ShowVersion(debugger.Output); } else { try { LispVariant result = Lisp.Eval(cmd, currentScope, currentScope.ModuleName); debugger.Output.WriteLine("result={0}", result); interactiveScript += cmd + '\n'; } catch (Exception ex) { debugger.Output.WriteLine("Exception: " + ex.Message); } } } while (!bContinueWithNextStatement); return(bRestart); }