diff options
Diffstat (limited to 'src/scripttools/debugging/scripts')
25 files changed, 1073 insertions, 0 deletions
diff --git a/src/scripttools/debugging/scripts/commands/advance.qs b/src/scripttools/debugging/scripts/commands/advance.qs new file mode 100644 index 0000000..2647dc1 --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/advance.qs @@ -0,0 +1,41 @@ +name = "advance"; + +group = "running"; + +shortDescription = "Continue the program up to the given location"; + +longDescription = "This command has the same syntax as the \"break\" command."; + +seeAlso = [ "break", "tbreak" ]; + +argumentTypes = [ "script-filename" ]; + +function execute() { + if (arguments.length == 0) { + message("Missing argument(s)."); + return; + } + var arg = arguments[0]; + var colonIndex = arg.lastIndexOf(':'); + if (colonIndex == -1) { + lineNumber = parseInt(arg); + if (isNaN(lineNumber)) { + message("Location must be of the form <file>:<line> or <line>."); + return; + } + var sid = getCurrentScriptId(); + if (sid == -1) { + message("No script."); + return; + } + scheduleRunToLocation(sid, lineNumber); + } else { + fileName = arg.slice(0, colonIndex); + lineNumber = parseInt(arg.slice(colonIndex+1)); + // ### resolve the script to see if it's loaded or not? (e.g. so we can issue a warning) + scheduleRunToLocation(fileName, lineNumber); + } +} + +function handleResponse(resp) { +} diff --git a/src/scripttools/debugging/scripts/commands/backtrace.qs b/src/scripttools/debugging/scripts/commands/backtrace.qs new file mode 100644 index 0000000..4e959fd --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/backtrace.qs @@ -0,0 +1,26 @@ +name = "backtrace"; + +group = "stack"; + +shortDescription = "Print backtrace of stack frames"; + +longDescription = ""; + +aliases = [ "bt" ]; + +seeAlso = [ "frame", "info" ]; + +function execute() { + scheduleGetBacktrace(); +}; + +function handleResponse(resp) { + var strings = resp.result; + var msg = ""; + for (var i = 0; i < strings.length; ++i) { + if (i > 0) + msg += "\n"; + msg += "#" + i + " " + strings[i]; + } + message(msg); +} diff --git a/src/scripttools/debugging/scripts/commands/break.qs b/src/scripttools/debugging/scripts/commands/break.qs new file mode 100644 index 0000000..8363685 --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/break.qs @@ -0,0 +1,59 @@ +name = "break"; + +group = "breakpoints"; + +shortDescription = "Set a breakpoint at specified location"; + +longDescription = "break <file>:<line> : Sets a breakpoint at the given location."; +longDescription += "\nbreak <line> : Sets a breakpoint at the given line of the current file."; + +argumentTypes = [ "script-filename" ]; + +aliases = [ "b" ]; + +seeAlso = [ "condition", "delete", "disable", "tbreak" ]; + +function execute() { + if (arguments.length == 0) { + message("Missing argument."); + return; + } + var arg = arguments[0]; + var colonIndex = arg.lastIndexOf(':'); + if (colonIndex == -1) { + lineNumber = parseInt(arg); + if (isNaN(lineNumber)) { + message("Breakpoint location must be of the form <file>:<line> or <line>."); + return; + } + var sid = getCurrentScriptId(); + if (sid == -1) { + message("No script."); + return; + } + scheduleGetScriptData(sid); + scriptId = sid; + state = 1; + } else { + fileName = arg.slice(0, colonIndex); + lineNumber = parseInt(arg.slice(colonIndex+1)); + // ### resolve the script to see if it's loaded or not? (e.g. so we can issue a warning) + scheduleSetBreakpoint({ fileName: fileName, lineNumber: lineNumber}); + state = 2; + } +} + +function handleResponse(resp) { + if (state == 1) { + fileName = resp.result.fileName; + if (fileName.length == 0) + fileName = "<anonymous script, id=" + scriptId + ">"; + scheduleSetBreakpoint({ scriptId: scriptId, lineNumber: lineNumber}); + state = 2; + } else if (state == 2) { + if (resp.error == 0) { + var id = resp.result; + message("Breakpoint " + id + ": " + fileName + ", line " + lineNumber + "."); + } + } +} diff --git a/src/scripttools/debugging/scripts/commands/clear.qs b/src/scripttools/debugging/scripts/commands/clear.qs new file mode 100644 index 0000000..3a22587 --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/clear.qs @@ -0,0 +1,59 @@ +name = "clear"; + +group = "breakpoints"; + +shortDescription = "Clear breakpoint at specified location"; + +longDescription = "clear <file>:<line> : Clear breakpoints at the given location."; +longDescription += "\nclear <line> : Clear breakpoints at the given line of the current script."; + +seeAlso = [ "delete" ]; + +argumentTypes = [ "script-filename" ]; + +function execute() { + if (arguments.length == 0) { + message("Missing argument."); + return; + } + var arg = arguments[0]; + var colonIndex = arg.lastIndexOf(':'); + if (colonIndex == -1) { + lineNumber = parseInt(arg); + if (isNaN(lineNumber)) { + message("Breakpoint location must be of the form <file>:<line> or <line>."); + return; + } + var sid = getCurrentScriptId(); + if (sid == -1) { + message("No script."); + return; + } + scriptId = sid; + } else { + fileName = arg.slice(0, colonIndex); + lineNumber = parseInt(arg.slice(colonIndex+1)); + } + scheduleGetBreakpoints(); + state = 1; +} + +function handleResponse(resp) { + if (state == 1) { + var breakpoints = resp.result; + if (breakpoints == undefined) + return; + for (var id in breakpoints) { + var data = breakpoints[id]; + if ((data.lineNumber == lineNumber) + && (data.fileName == fileName) + || ((data.scriptId != -1) && (data.scriptId = scriptId))) { + scheduleDeleteBreakpoint(id); + message("Deleted breakpoint " + id + "."); + } + } + state = 2; + } else if (state == 2) { + + } +} diff --git a/src/scripttools/debugging/scripts/commands/complete.qs b/src/scripttools/debugging/scripts/commands/complete.qs new file mode 100644 index 0000000..9d60312 --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/complete.qs @@ -0,0 +1,14 @@ +name = "complete"; + +group = "void"; + +shortDescription = "List the completions for the rest of the line as a command"; + +longDescription = ""; + +function execute() { + var prefix = (arguments.length > 0) ? arguments[0] : ""; + var completions = getCommandCompletions(prefix); + for (var i = 0; i < completions.length; ++i) + message(completions[i]); +} diff --git a/src/scripttools/debugging/scripts/commands/condition.qs b/src/scripttools/debugging/scripts/commands/condition.qs new file mode 100644 index 0000000..9bf6ae2 --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/condition.qs @@ -0,0 +1,52 @@ +name = "condition"; + +group = "breakpoints"; + +shortDescription = "Specify breakpoint condition"; + +longDescription = "condition <breakpoint-id> <expression> : Specify that the breakpoint with the given id should only be triggered if the given expression evaluates to true."; + +argumentTypes = [ "breakpoint-id", "script" ]; + +seeAlso = [ "ignore" ]; + +function execute() { + if (arguments.length == 0) { + message("Missing arguments (breakpoint number and condition)."); + return; + } + var arg = arguments[0]; + var spaceIndex = arg.indexOf(' '); + if (spaceIndex == -1) + spaceIndex = arg.length; + var id = parseInt(arg.slice(0, spaceIndex)); + if (isNaN(id)) { + message("First argument must be a number (breakpoint id)."); + return; + } + var cond = arg.slice(spaceIndex+1); + if ((cond.length != 0) && !checkSyntax(cond)) { + message("The condition has a syntax error."); + return; + } + scheduleGetBreakpointData(id); + breakpointId = id; + condition = cond; + state = 1; +} + +function handleResponse(resp) { + if (state == 1) { + var data = resp.result; + if (data == undefined) { + message("No breakpoint number " + breakpointId + "."); + return; + } + data.condition = condition; + scheduleSetBreakpointData(breakpointId, data); + state = 2; + } else if (state == 2) { + if (condition.length == 0) + message("Breakpoint " + breakpointId + " now unconditional."); + } +} diff --git a/src/scripttools/debugging/scripts/commands/continue.qs b/src/scripttools/debugging/scripts/commands/continue.qs new file mode 100644 index 0000000..a940f13 --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/continue.qs @@ -0,0 +1,22 @@ +name = "continue"; + +group = "running"; + +shortDescription = "Continue evaluation"; + +longDescription = "Evaluation will continue until an uncaught exception occurs, " +longDescription += "a breakpoint is hit or evaluation is explicitly interrupted."; + +aliases = [ "c", "fg" ]; + +seeAlso = [ "step", "interrupt" ]; + +function execute() { + scheduleContinue(); +}; + +function handleResponse(resp) { + if (!resp.async) { + message("The target is not evaluating code."); + } +} diff --git a/src/scripttools/debugging/scripts/commands/delete.qs b/src/scripttools/debugging/scripts/commands/delete.qs new file mode 100644 index 0000000..84497a7 --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/delete.qs @@ -0,0 +1,36 @@ +name = "delete"; + +group = "breakpoints"; + +shortDescription = "Delete breakpoint(s)"; + +longDescription = "delete <breakpoint-id> : Deletes the breakpoint with the given id."; + +seeAlso = [ "clear", "disable" ]; + +function execute() { + if (arguments.length == 0) { + // delete all breakpoints + scheduleClearBreakpoints(); + state = 1; + } else { + var id = parseInt(arguments[0]); + if (isNaN(id)) { + message("Breakpoint id expected."); + return; + } + scheduleDeleteBreakpoint(id); + breakpointId = id; + state = 2; + } +} + +function handleResponse(resp) { + if (state == 1) { + } else if (state == 2) { + if (resp.error != 0) { + message("No breakpoint number " + breakpointId + "."); + return; + } + } +} diff --git a/src/scripttools/debugging/scripts/commands/disable.qs b/src/scripttools/debugging/scripts/commands/disable.qs new file mode 100644 index 0000000..91bf44b --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/disable.qs @@ -0,0 +1,56 @@ +name = "disable"; + +group = "breakpoints"; + +shortDescription = "Disable breakpoint(s)"; + +longDescription = "disable <breakpoint-id> : Disables the breakpoint with the given id."; + +seeAlso = [ "enable", "delete", "ignore" ]; + +function execute() { + if (arguments.length == 0) { + // disable all breakpoints + state = 1; + scheduleGetBreakpoints(); + } else { + var id = parseInt(arguments[0]); + if (isNaN(id)) { + message("Breakpoint id expected."); + return; + } + scheduleGetBreakpointData(id); + breakpointId = id; + state = 3; + } +}; + +function handleResponse(resp) { + if (state == 1) { + var breakpoints = resp.result; + if (breakpoints == undefined) + return; + for (var id in breakpoints) { + var data = breakpoints[id]; + if (data.enabled) { + data.enabled = false; + scheduleSetBreakpointData(id, data); + } + } + state = 2; + } else if (state == 2) { + state = 0; + } else if (state == 3) { + var data = resp.result; + if (data == undefined) { + message("No breakpoint number " + breakpointId + "."); + return; + } else if (data.enabled) { + data.enabled = false; + scheduleSetBreakpointData(breakpointId, data); + state = 4; + } + } else if (state == 4) { + state = 0; + } +} diff --git a/src/scripttools/debugging/scripts/commands/down.qs b/src/scripttools/debugging/scripts/commands/down.qs new file mode 100644 index 0000000..dc0429b --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/down.qs @@ -0,0 +1,33 @@ +name = "down"; + +group = "stack"; + +shortDescription = "Select and print the stack frame below the current one"; + +longDescription = ""; + +seeAlso = [ "up", "frame" ]; + +function execute() { + var idx = getCurrentFrameIndex(); + if (idx == 0) { + warning("Already at bottom (innermost) frame."); + return; + } + setCurrentFrameIndex(idx - 1); + scheduleGetContextInfo(idx - 1); + state = 1; +} + +function handleResponse(resp, id) { + if (state == 1) { + var info = resp.result; + setCurrentScriptId(info.scriptId); + setCurrentLineNumber(info.lineNumber); + scheduleGetBacktrace(); + state = 2; + } else if (state == 2) { + var backtrace = resp.result; + message("#" + getCurrentFrameIndex() + " " + backtrace[getCurrentFrameIndex()]); + } +} diff --git a/src/scripttools/debugging/scripts/commands/enable.qs b/src/scripttools/debugging/scripts/commands/enable.qs new file mode 100644 index 0000000..6468d0a --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/enable.qs @@ -0,0 +1,56 @@ +name = "enable"; + +group = "breakpoints"; + +shortDescription = "Enable breakpoint(s)"; + +longDescription = "enable <breakpoint-id> : Enable the breakpoint with the given id."; + +seeAlso = [ "disable" ]; + +function execute() { + if (arguments.length == 0) { + // enable all breakpoints + state = 1; + scheduleGetBreakpoints(); + } else { + var id = parseInt(arguments[0]); + if (isNaN(id)) { + message("Breakpoint id expected."); + return; + } + scheduleGetBreakpointData(id); + breakpointId = id; + state = 3; + } +}; + +function handleResponse(resp) { + if (state == 1) { + var breakpoints = resp.result; + if (breakpoints == undefined) + return; + for (var id in breakpoints) { + var data = breakpoints[id]; + if (!data.enabled) { + data.enabled = true; + scheduleSetBreakpointData(id, data); + } + } + state = 2; + } else if (state == 2) { + state = 0; + } else if (state == 3) { + var data = resp.result; + if (data == undefined) { + message("No breakpoint number " + breakpointId + "."); + return; + } else if (!data.enabled) { + data.enabled = true; + scheduleSetBreakpointData(breakpointId, data); + state = 4; + } + } else if (state == 4) { + state = 0; + } +} diff --git a/src/scripttools/debugging/scripts/commands/eval.qs b/src/scripttools/debugging/scripts/commands/eval.qs new file mode 100644 index 0000000..02a1b9f --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/eval.qs @@ -0,0 +1,21 @@ +name = "eval"; + +group = "running"; + +shortDescription = "Evaluate program"; + +longDescription = ""; + +argumentTypes = [ "script" ]; + +function execute() { + if (arguments.length == 0) { + message("Missing argument (program)."); + return; + } + setEvaluateAction(0); + scheduleEvaluate(getCurrentFrameIndex(), arguments[0], "console input (" + Date() + ")"); +}; + +function handleResponse(resp, id) { +} diff --git a/src/scripttools/debugging/scripts/commands/finish.qs b/src/scripttools/debugging/scripts/commands/finish.qs new file mode 100644 index 0000000..bf19fc0 --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/finish.qs @@ -0,0 +1,16 @@ +name = "finish"; + +group = "running"; + +shortDescription = "Execute until the current stack frame returns"; + +longDescription = "Upon return, the value returned is printed."; + +seeAlso = [ "next", "continue" ]; + +function execute() { + scheduleStepOut(); +}; + +function handleResponse(resp) { +} diff --git a/src/scripttools/debugging/scripts/commands/frame.qs b/src/scripttools/debugging/scripts/commands/frame.qs new file mode 100644 index 0000000..5dc4611 --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/frame.qs @@ -0,0 +1,36 @@ +name = "frame"; + +group = "stack"; + +shortDescription = "Select and print a stack frame"; + +longDescription = ""; + +aliases = [ "f" ]; + +function execute() { + if (arguments.length == 0) + requestedFrameIndex = getCurrentFrameIndex(); + else + requestedFrameIndex = parseInt(arguments[0]); + scheduleGetContextInfo(requestedFrameIndex); + state = 1; +}; + +function handleResponse(resp, id) { + if (state == 1) { + var info = resp.result; + if (info == undefined) { + message("Frame index out of range."); + return; + } + setCurrentFrameIndex(requestedFrameIndex); + setCurrentScriptId(info.scriptId); + setCurrentLineNumber(info.lineNumber); + scheduleGetBacktrace(); + state = 2; + } else if (state == 2) { + var backtrace = resp.result; + message("#" + getCurrentFrameIndex() + " " + backtrace[getCurrentFrameIndex()]); + } +} diff --git a/src/scripttools/debugging/scripts/commands/help.qs b/src/scripttools/debugging/scripts/commands/help.qs new file mode 100644 index 0000000..121db11 --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/help.qs @@ -0,0 +1,71 @@ +name = "help"; + +group = "void"; + +shortDescription = "Print list of commands"; + +longDescription = ""; + +argumentTypes = [ "command-or-group-name" ]; + +function execute() { + if (arguments.length == 0) { + var groups = getCommandGroups(); + message("List of command categories:"); + message(""); + for (var name in groups) { + if (name == "void") + continue; + var data = groups[name]; + message(name + " :: " + data.shortDescription); + } + message(""); + message("Type \"help\" followed by a category name for a list of commands in that category."); + message("Type \"help all\" for the list of all commands."); + message("Type \"help\" followed by a command name for full documentation."); + message("Command name abbreviations are allowed if they are unambiguous."); + } else { + var arg = arguments[0]; + if (arg == "all") { + var groups = getCommandGroups(); + for (var name in groups) { + if (name == "void") + continue; + message("Command category: " + name); + message(""); + var commands = getCommandsInGroup(name); + for (var i = 0; i < commands.length; ++i) { + var data = commands[i]; + message(data.name + " :: " + data.shortDescription); + } + message(""); + } + } else { + var data = findCommand(arg); + if (data != undefined) { + message(data.shortDescription + "."); + if (data.longDescription.length != 0) + message(data.longDescription); + if (data.aliases.length != 0) + message("Aliases: " + data.aliases.join(", ")); + if (data.seeAlso.length != 0) + message("See also: " + data.seeAlso.join(", ")); + } else { + data = getCommandGroups()[arg]; + if (data != undefined) { + message(data.shortDescription + "."); + message(""); + message("List of commands:"); + message(""); + var commands = getCommandsInGroup(arg); + for (var i = 0; i < commands.length; ++i) { + var data = commands[i]; + message(data.name + " :: " + data.shortDescription); + } + } else { + message("Undefined command \"" + arg + "\". Try \"help\"."); + } + } + } + } +}; diff --git a/src/scripttools/debugging/scripts/commands/ignore.qs b/src/scripttools/debugging/scripts/commands/ignore.qs new file mode 100644 index 0000000..b625bae --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/ignore.qs @@ -0,0 +1,51 @@ +name = "ignore"; + +group = "breakpoints"; + +shortDescription = "Set ignore-count of a breakpoint"; + +longDescription = "ignore <breakpoint-id> <count> : Ignores the breakpoint with the given id the next count times it is hit."; + +seeAlso = [ "condition" ]; + +function execute() { + if (arguments.length < 1) { + message("Missing arguments (breakpoing number and ignore-count)."); + return; + } + if (arguments.length < 2) { + message("Missing argument (ignore-count)."); + return; + } + var id = parseInt(arguments[0]); + if (isNaN(id)) { + message("First argument (breakpoint id) must be a number."); + return; + } + var count = parseInt(arguments[1]); + if (isNaN(count)) { + message("Second argument (ignore-count) must be a number."); + return; + } + scheduleGetBreakpointData(id); + breakpointId = id; + if (count < 0) + count = 0; + ignoreCount = count; + state = 1; +} + +function handleResponse(resp) { + if (state == 1) { + var data = resp.result; + if (data == undefined) { + message("No breakpoint number " + breakpointId + "."); + return; + } + data.ignoreCount = ignoreCount; + scheduleSetBreakpointData(breakpointId, data); + state = 2; + } else if (state == 2) { + message("Breakpoint " + breakpointId + " will be ignored the next " + ignoreCount + " time(s)."); + } +} diff --git a/src/scripttools/debugging/scripts/commands/info.qs b/src/scripttools/debugging/scripts/commands/info.qs new file mode 100644 index 0000000..2577e92 --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/info.qs @@ -0,0 +1,128 @@ +name = "info"; + +group = "status"; + +shortDescription = "Display information about something"; + +longDescription = "info scripts : Names of scripts being debugged"; +longDescription += "\ninfo breakpoints : Status of breakpoints currently set"; +longDescription += "\ninfo locals : Local variables of current stack frame"; + +argumentTypes = [ "subcommand-name" ]; + +subCommands = [ "breakpoints", "locals", "scripts" ]; + +function execute() { + var arg = arguments[0]; + if (arg == undefined) { + message("\"info\" must be followed by the name of an info command."); + return; + } else if (arg == "scripts") { + scheduleGetScripts(); + state = 1; + } else if (arg == "breakpoints") { + if (arguments.length > 1) { + var id = parseInt(arguments[1]); + if (isNaN(id)) { + message("Breakpoint id expected."); + return; + } + scheduleGetBreakpointData(id); + breakpointId = id; + state = 3; + } else { + scheduleGetBreakpoints(); + state = 2; + } + } else if (arg == "locals") { + scheduleGetActivationObject(getCurrentFrameIndex()); + state = 4; + } else { + warning("Undefined info command \"" + arg + "\". Try \"help info\"."); + } +} + +function breakpointString(id, data) { + var fn = data.fileName; + if (fn.length == 0) + fn = "<anonymous script, id=" + data.scriptId + ">"; + var ret = id + "\t" + (data.enabled ? "yes" : "no") + + "\t" + fn + ":" + data.lineNumber; + if (data.condition.length != 0) { + ret += "\n\tstop only if " + data.condition; + } + return ret; +} + +function handleResponse(resp) { + if (state == 1) { + // info scripts + var scripts = resp.result; + if (scripts == undefined) { + message("No scripts loaded."); + return; + } + for (var id in scripts) { + var fn = scripts[id].fileName; + if (fn.length == 0) + fn = "<anonymous script, id=" + id + ">"; + message("\t" + fn); + } + } + + else if (state == 2) { + // info breakpoints + var breakpoints = resp.result; + if (breakpoints == undefined) { + message("No breakpoints set."); + return; + } + message("Id\tEnabled\tWhere"); + for (var id in breakpoints) { + var data = breakpoints[id]; + message(breakpointString(id, data)); + } + } else if (state == 3) { + // info breakpoints N + var data = resp.result; + if (data == undefined) { + message("No breakpoint number " + breakpointId + "."); + return; + } + message("Id\tEnabled\tWhere"); + message(breakpointString(breakpointId, data)); + } + + else if (state == 4) { + // info locals + var act = resp.result; + scheduleNewScriptValueIterator(act); + state = 5; + } else if (state == 5) { + var id = resp.result; + scheduleGetPropertiesByIterator(id, 100); + iteratorId = id; + state = 6; + } else if (state == 6) { + var props = resp.result; + if (props.length == 0) { + scheduleDeleteScriptValueIterator(iteratorId); + state = 7; + return; + } + var maxLength = 0; + for (var i = 0; i < props.length; ++i) + maxLength = Math.max(props[i].name.length, maxLength); + for (var i = 0; i < props.length; ++i) { + var prop = props[i]; + var msg = prop.name; + var pad = maxLength - prop.name.length; + for (var j = 0; j < pad; ++j) + msg += ' '; + message(msg + " : " + prop.valueAsString); + } + scheduleGetPropertiesByIterator(iteratorId, 100); + } else if (state == 7) { + // done + } +} diff --git a/src/scripttools/debugging/scripts/commands/interrupt.qs b/src/scripttools/debugging/scripts/commands/interrupt.qs new file mode 100644 index 0000000..d4b66cc --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/interrupt.qs @@ -0,0 +1,14 @@ +name = "interrupt"; + +group = "running"; + +shortDescription = "Interrupt evaluation"; + +longDescription = "Interruption will occur as soon as a new script statement is reached."; + +function execute() { + scheduleInterrupt(); +} + +function handleResponse(resp) { +} diff --git a/src/scripttools/debugging/scripts/commands/list.qs b/src/scripttools/debugging/scripts/commands/list.qs new file mode 100644 index 0000000..312b123 --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/list.qs @@ -0,0 +1,90 @@ +name = "list"; + +group = "files"; + +shortDescription = "List lines of a script"; + +longDescription = "list <file>:<line> : Lists lines around the given location."; +longDescription += "\nlist <line> : Lists lines in the current file."; + +argumentTypes = [ "script-filename" ]; + +listLineNumber = 1; +listScriptId = -1; +lastSessionId = -1; +lastFrameIndex = -1; + +function execute() { + state = 0; + if (arguments.length > 0) { + var arg = arguments[0]; + var colonIndex = arg.lastIndexOf(':'); + var fileName; + var lineNumber; + if (colonIndex == -1) { + lineNumber = parseInt(arg); + if (isNaN(lineNumber)) { + fileName = arg; + lineNumber = 1; + } + } else if (colonIndex == 0) { + fileName = arg; + lineNumber = 1; + } else { + fileName = arg.slice(0, colonIndex); + lineNumber = parseInt(arg.slice(colonIndex+1)); + } + listLineNumber = Math.max(lineNumber, 1); + if (fileName != undefined) { + scheduleResolveScript(fileName); + state = 1; + } else { + setCurrentLineNumber(listLineNumber); + execute(); + } + } else { + if ((getSessionId() != lastSessionId) + || (getCurrentFrameIndex() != lastFrameIndex) + || (listScriptId == -1)) { + listScriptId = getCurrentScriptId(); + listLineNumber = getCurrentLineNumber(); + lastSessionId = getSessionId(); + lastFrameIndex = getCurrentFrameIndex(); + } + scheduleGetScriptData(listScriptId); + state = 2; + } +}; + +function handleResponse(resp) { + if (state == 1) { + var id = resp.result; + if (id == -1) { + message("That script isn't loaded."); + state = 0; + return; + } + listScriptId = id; + scheduleGetScriptData(listScriptId); + state = 2; + } else if (state == 2) { + var data = resp.result; + if (data == undefined) { + message("No script."); + state = 0; + return; + } + var base = data.baseLineNumber; + var lines = data.contents.split('\n'); + var start = Math.max(listLineNumber - 5, base); + for (var i = start; i < start + 10; ++i) { + var ln = lines[i - base]; + var msg = String(i); + if (ln != undefined) + msg += "\t" + ln; + message(msg); + } + listLineNumber += 10; + state = 0; + } +} diff --git a/src/scripttools/debugging/scripts/commands/next.qs b/src/scripttools/debugging/scripts/commands/next.qs new file mode 100644 index 0000000..bc37a01 --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/next.qs @@ -0,0 +1,27 @@ +name = "next"; + +group = "running"; + +shortDescription = "Step program, proceeding through subroutine calls"; + +longDescription = "Like the \"step\" command as long as subroutine calls do not happen;"; +longDescription += "\nwhen they do, the call is treated as one instruction."; +longDescription += "\nIf a number N is given as argument, this will be done N times before execution is stopped."; +aliases = [ "n" ]; + +seeAlso = [ "step", "continue", "finish", "advance" ]; + +function execute() { + var count = 1; + if (arguments.length != 0) { + var arg = arguments[0]; + // ### evaluate the expression in the current frame? + var num = parseInt(arg); + if (!isNaN(num) && (num >= 1)) + count = num; + } + scheduleStepOver(count); +}; + +function handleResponse(resp) { +} diff --git a/src/scripttools/debugging/scripts/commands/print.qs b/src/scripttools/debugging/scripts/commands/print.qs new file mode 100644 index 0000000..9b98d16 --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/print.qs @@ -0,0 +1,23 @@ +// ### exactly the same as eval, but provided for convenience + +name = "print"; + +group = "status"; + +shortDescription = "Print value of an expression"; + +longDescription = ""; + +argumentTypes = [ "script" ]; + +function execute() { + if (arguments.length == 0) { + message("Missing argument (expression)."); + return; + } + setEvaluateAction(0); + scheduleEvaluate(getCurrentFrameIndex(), arguments[0], "console input (" + Date() + ")"); +}; + +function handleResponse(resp, id) { +} diff --git a/src/scripttools/debugging/scripts/commands/return.qs b/src/scripttools/debugging/scripts/commands/return.qs new file mode 100644 index 0000000..372c818 --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/return.qs @@ -0,0 +1,20 @@ +name = "return"; + +group = "running"; + +shortDescription = "Make selected stack frame return to its caller"; + +longDescription = ""; + +argumentTypes = [ "script" ]; + +function execute() { + // TODO: + // 1. schedule evaluate of the expression. + // 2. install event handler/filter, so that we're notified when the evaluate is done. + // - what if another event occurs while we evaluate? (e.g. an exception or breakpoint) + // - the event filter needs to uninstall itself, or the event needs to be consumed internally + // 3. in the event handler, schedule forced return with the result as argument. + setEvaluateAction(1); + scheduleEvaluate(getCurrentFrameIndex(), arguments[0], "console input (" + Date() + ")"); +}; diff --git a/src/scripttools/debugging/scripts/commands/step.qs b/src/scripttools/debugging/scripts/commands/step.qs new file mode 100644 index 0000000..1aacec0 --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/step.qs @@ -0,0 +1,26 @@ +name = "step"; + +group = "running"; + +shortDescription = "Step program until a new statement is reached"; + +longDescription = "If a number N is given as argument, this will be done N times before execution is stopped."; + +aliases = [ "s" ]; + +seeAlso = [ "next" ]; + +function execute() { + var count = 1; + if (arguments.length != 0) { + var arg = arguments[0]; + // ### evaluate the expression in the current frame? + var num = parseInt(arg); + if (!isNaN(num) && (num >= 1)) + count = num; + } + scheduleStepInto(count); +}; + +function handleResponse(resp) { +} diff --git a/src/scripttools/debugging/scripts/commands/tbreak.qs b/src/scripttools/debugging/scripts/commands/tbreak.qs new file mode 100644 index 0000000..66a8224 --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/tbreak.qs @@ -0,0 +1,59 @@ +name = "tbreak"; + +group = "breakpoints"; + +shortDescription = "Set a temporary breakpoint"; + +longDescription = "The same as the \"break\" command, except that the breakpoint is automatically deleted as soon as it is triggered."; + +seeAlso = [ "break", "ignore" ]; + +argumentTypes = [ "script-filename" ]; + +// ### merge with break.qs: only difference is the "singleShot: true" in call to scheduleSetBreakpoint() +// ### maybe an include() function so commands can share code? + +function execute() { + if (arguments.length == 0) { + message("Missing argument."); + return; + } + var arg = arguments[0]; + var colonIndex = arg.lastIndexOf(':'); + if (colonIndex == -1) { + lineNumber = parseInt(arg); + if (isNaN(lineNumber)) { + message("Breakpoint location must be of the form <file>:<line> or <line>."); + return; + } + var sid = getCurrentScriptId(); + if (sid == -1) { + message("No script."); + return; + } + scheduleGetScriptData(sid); + scriptId = sid; + state = 1; + } else { + fileName = arg.slice(0, colonIndex); + lineNumber = parseInt(arg.slice(colonIndex+1)); + // ### resolve the script to see if it's loaded or not? (e.g. so we can issue a warning) + scheduleSetBreakpoint({ fileName: fileName, lineNumber: lineNumber, singleShot: true }); + state = 2; + } +} + +function handleResponse(resp) { + if (state == 1) { + fileName = resp.result.fileName; + if (fileName.length == 0) + fileName = "<anonymous script, id=" + scriptId + ">"; + scheduleSetBreakpoint({ scriptId: scriptId, lineNumber: lineNumber, singleShot: true }); + state = 2; + } else if (state == 2) { + if (resp.error == 0) { + var id = resp.result; + message("Breakpoint " + id + ": " + fileName + ", line " + lineNumber + "."); + } + } +} diff --git a/src/scripttools/debugging/scripts/commands/up.qs b/src/scripttools/debugging/scripts/commands/up.qs new file mode 100644 index 0000000..2d49df3 --- /dev/null +++ b/src/scripttools/debugging/scripts/commands/up.qs @@ -0,0 +1,37 @@ +name = "up"; + +group = "stack"; + +shortDescription = "Select and print the stack frame above the current one"; + +longDescription = ""; + +seeAlso = [ "down", "frame" ]; + +function execute() { + scheduleGetContextCount(); + state = 1; +} + +function handleResponse(resp) { + if (state == 1) { + var count = resp.result; + var idx = getCurrentFrameIndex() + 1; + if (idx == count) { + warning("Already at top (outermost) frame."); + return; + } + setCurrentFrameIndex(idx); + scheduleGetContextInfo(idx); + state = 2; + } else if (state == 2) { + var info = resp.result; + setCurrentScriptId(info.scriptId); + setCurrentLineNumber(info.lineNumber); + scheduleGetBacktrace(); + state = 3; + } else if (state == 3) { + var backtrace = resp.result; + message("#" + getCurrentFrameIndex() + " " + backtrace[getCurrentFrameIndex()]); + } +} |