parent
d3b0bb79a1
commit
5fc8765678
5 changed files with 144 additions and 33 deletions
|
|
@ -18,6 +18,7 @@ export interface Variable {
|
||||||
name: string;
|
name: string;
|
||||||
valueStr: string;
|
valueStr: string;
|
||||||
type: string;
|
type: string;
|
||||||
|
raw?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SSHArguments {
|
export interface SSHArguments {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
const resultRegex = /^([a-zA-Z_\-][a-zA-Z0-9_\-]*)\s*=\s*/;
|
import { MINode } from "./mi_parse"
|
||||||
|
|
||||||
|
const resultRegex = /^([a-zA-Z_\-][a-zA-Z0-9_\-]*|\[\d+\])\s*=\s*/;
|
||||||
const variableRegex = /^[a-zA-Z_\-][a-zA-Z0-9_\-]*/;
|
const variableRegex = /^[a-zA-Z_\-][a-zA-Z0-9_\-]*/;
|
||||||
const errorRegex = /^\<.+?\>/;
|
const errorRegex = /^\<.+?\>/;
|
||||||
const referenceStringRegex = /^(0x[0-9a-fA-F]+\s*)"/;
|
const referenceStringRegex = /^(0x[0-9a-fA-F]+\s*)"/;
|
||||||
|
|
@ -18,6 +20,7 @@ export function isExpandable(value: string): number {
|
||||||
else if (value.startsWith("true")) return 0;
|
else if (value.startsWith("true")) return 0;
|
||||||
else if (value.startsWith("false")) return 0;
|
else if (value.startsWith("false")) return 0;
|
||||||
else if (match = nullpointerRegex.exec(value)) return 0;
|
else if (match = nullpointerRegex.exec(value)) return 0;
|
||||||
|
else if (match = referenceStringRegex.exec(value)) return 0;
|
||||||
else if (match = referenceRegex.exec(value)) return 2; // reference
|
else if (match = referenceRegex.exec(value)) return 2; // reference
|
||||||
else if (match = charRegex.exec(value)) return 0;
|
else if (match = charRegex.exec(value)) return 0;
|
||||||
else if (match = numberRegex.exec(value)) return 0;
|
else if (match = numberRegex.exec(value)) return 0;
|
||||||
|
|
@ -26,7 +29,7 @@ export function isExpandable(value: string): number {
|
||||||
else return 0;
|
else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function expandValue(variableCreate: Function, value: string, root: string = ""): any {
|
export function expandValue(variableCreate: Function, value: string, root: string = "", extra: any = undefined): any {
|
||||||
let parseCString = () => {
|
let parseCString = () => {
|
||||||
value = value.trim();
|
value = value.trim();
|
||||||
if (value[0] != '"' && value[0] != '\'')
|
if (value[0] != '"' && value[0] != '\'')
|
||||||
|
|
@ -155,10 +158,10 @@ export function expandValue(variableCreate: Function, value: string, root: strin
|
||||||
}
|
}
|
||||||
else if (match = nullpointerRegex.exec(value)) {
|
else if (match = nullpointerRegex.exec(value)) {
|
||||||
primitive = "<nullptr>";
|
primitive = "<nullptr>";
|
||||||
value = value.substr(3).trim();
|
value = value.substr(match[0].length).trim();
|
||||||
}
|
}
|
||||||
else if (match = referenceStringRegex.exec(value)) {
|
else if (match = referenceStringRegex.exec(value)) {
|
||||||
value = value.substr(match[1].length);
|
value = value.substr(match[1].length).trim();
|
||||||
primitive = parseCString();
|
primitive = parseCString();
|
||||||
}
|
}
|
||||||
else if (match = referenceRegex.exec(value)) {
|
else if (match = referenceRegex.exec(value)) {
|
||||||
|
|
@ -183,7 +186,7 @@ export function expandValue(variableCreate: Function, value: string, root: strin
|
||||||
value = value.substr(match[0].length).trim();
|
value = value.substr(match[0].length).trim();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
primitive = "<???>";
|
primitive = value;
|
||||||
}
|
}
|
||||||
return primitive;
|
return primitive;
|
||||||
};
|
};
|
||||||
|
|
@ -220,8 +223,16 @@ export function expandValue(variableCreate: Function, value: string, root: strin
|
||||||
val = "Object";
|
val = "Object";
|
||||||
}
|
}
|
||||||
if (typeof val == "string" && val.startsWith("*0x")) {
|
if (typeof val == "string" && val.startsWith("*0x")) {
|
||||||
ref = variableCreate(getNamespace("*" + name));
|
if (extra && MINode.valueOf(extra, "arg") == "1")
|
||||||
val = "Object@" + val;
|
{
|
||||||
|
ref = variableCreate(getNamespace("*(" + name), { arg: true });
|
||||||
|
val = "<args>";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ref = variableCreate(getNamespace("*" + name));
|
||||||
|
val = "Object@" + val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (typeof val == "string" && val.startsWith("<...>")) {
|
if (typeof val == "string" && val.startsWith("<...>")) {
|
||||||
ref = variableCreate(getNamespace(name));
|
ref = variableCreate(getNamespace(name));
|
||||||
|
|
|
||||||
|
|
@ -549,7 +549,8 @@ export class MI2 extends EventEmitter implements IBackend {
|
||||||
ret.push({
|
ret.push({
|
||||||
name: key,
|
name: key,
|
||||||
valueStr: value,
|
valueStr: value,
|
||||||
type: type
|
type: type,
|
||||||
|
raw: element
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
resolve(ret);
|
resolve(ret);
|
||||||
|
|
|
||||||
135
src/mibase.ts
135
src/mibase.ts
|
|
@ -13,6 +13,11 @@ import * as fs from "fs";
|
||||||
let resolve = posix.resolve;
|
let resolve = posix.resolve;
|
||||||
let relative = posix.relative;
|
let relative = posix.relative;
|
||||||
|
|
||||||
|
class ExtendedVariable {
|
||||||
|
constructor(public name, public options) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class MI2DebugSession extends DebugSession {
|
export class MI2DebugSession extends DebugSession {
|
||||||
protected variableHandles = new Handles<any>();
|
protected variableHandles = new Handles<any>();
|
||||||
protected quit: boolean;
|
protected quit: boolean;
|
||||||
|
|
@ -242,8 +247,11 @@ export class MI2DebugSession extends DebugSession {
|
||||||
const variables: DebugProtocol.Variable[] = [];
|
const variables: DebugProtocol.Variable[] = [];
|
||||||
const id = this.variableHandles.get(args.variablesReference);
|
const id = this.variableHandles.get(args.variablesReference);
|
||||||
|
|
||||||
let createVariable = (arg) => {
|
let createVariable = (arg, options?) => {
|
||||||
return this.variableHandles.create(arg);
|
if (options)
|
||||||
|
return this.variableHandles.create(new ExtendedVariable(arg, options));
|
||||||
|
else
|
||||||
|
return this.variableHandles.create(arg);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeof id == "string") {
|
if (typeof id == "string") {
|
||||||
|
|
@ -251,7 +259,7 @@ export class MI2DebugSession extends DebugSession {
|
||||||
this.miDebugger.getStackVariables(this.threadID, parseInt(id.substr("@frame:".length))).then(stack => {
|
this.miDebugger.getStackVariables(this.threadID, parseInt(id.substr("@frame:".length))).then(stack => {
|
||||||
stack.forEach(variable => {
|
stack.forEach(variable => {
|
||||||
if (variable.valueStr !== undefined) {
|
if (variable.valueStr !== undefined) {
|
||||||
let expanded = expandValue(createVariable, "{" + variable.name + "=" + variable.valueStr + ")");
|
let expanded = expandValue(createVariable, "{" + variable.name + "=" + variable.valueStr + ")", "", variable.raw);
|
||||||
if (expanded) {
|
if (expanded) {
|
||||||
if (typeof expanded[0] == "string")
|
if (typeof expanded[0] == "string")
|
||||||
expanded = [
|
expanded = [
|
||||||
|
|
@ -282,23 +290,28 @@ export class MI2DebugSession extends DebugSession {
|
||||||
else {
|
else {
|
||||||
// Variable members
|
// Variable members
|
||||||
this.miDebugger.evalExpression(JSON.stringify(id)).then(variable => {
|
this.miDebugger.evalExpression(JSON.stringify(id)).then(variable => {
|
||||||
let expanded = expandValue(createVariable, variable.result("value"), id);
|
try {
|
||||||
if (!expanded) {
|
let expanded = expandValue(createVariable, variable.result("value"), id, variable);
|
||||||
this.sendErrorResponse(response, 2, `Could not expand variable`);
|
if (!expanded) {
|
||||||
|
this.sendErrorResponse(response, 2, `Could not expand variable`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (typeof expanded[0] == "string")
|
||||||
|
expanded = [
|
||||||
|
{
|
||||||
|
name: "<value>",
|
||||||
|
value: prettyStringArray(expanded),
|
||||||
|
variablesReference: 0
|
||||||
|
}
|
||||||
|
];
|
||||||
|
response.body = {
|
||||||
|
variables: expanded
|
||||||
|
};
|
||||||
|
this.sendResponse(response);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
catch (e) {
|
||||||
if (typeof expanded[0] == "string")
|
this.sendErrorResponse(response, 2, `Could not expand variable: ` + e);
|
||||||
expanded = [
|
|
||||||
{
|
|
||||||
name: "<value>",
|
|
||||||
value: prettyStringArray(expanded),
|
|
||||||
variablesReference: 0
|
|
||||||
}
|
|
||||||
];
|
|
||||||
response.body = {
|
|
||||||
variables: expanded
|
|
||||||
};
|
|
||||||
this.sendResponse(response);
|
|
||||||
}
|
}
|
||||||
}, err => {
|
}, err => {
|
||||||
this.sendErrorResponse(response, 1, `Could not expand variable`);
|
this.sendErrorResponse(response, 1, `Could not expand variable`);
|
||||||
|
|
@ -306,10 +319,76 @@ export class MI2DebugSession extends DebugSession {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (typeof id == "object") {
|
else if (typeof id == "object") {
|
||||||
response.body = {
|
if (id instanceof ExtendedVariable) {
|
||||||
variables: id
|
let varReq = <ExtendedVariable>id;
|
||||||
};
|
if (varReq.options.arg) {
|
||||||
this.sendResponse(response);
|
let strArr = [];
|
||||||
|
let argsPart = true;
|
||||||
|
let arrIndex = 0;
|
||||||
|
let submit = () => {
|
||||||
|
response.body = {
|
||||||
|
variables: strArr
|
||||||
|
};
|
||||||
|
this.sendResponse(response);
|
||||||
|
};
|
||||||
|
let addOne = () => {
|
||||||
|
this.miDebugger.evalExpression(JSON.stringify(varReq.name + "+" + arrIndex + ")")).then(variable => {
|
||||||
|
try {
|
||||||
|
let expanded = expandValue(createVariable, variable.result("value"), id, variable);
|
||||||
|
if (!expanded) {
|
||||||
|
this.sendErrorResponse(response, 15, `Could not expand variable`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (typeof expanded == "string") {
|
||||||
|
if (expanded == "<nullptr>")
|
||||||
|
{
|
||||||
|
if (argsPart)
|
||||||
|
argsPart = false;
|
||||||
|
else
|
||||||
|
return submit();
|
||||||
|
}
|
||||||
|
else if (expanded[0] != '"')
|
||||||
|
{
|
||||||
|
strArr.push({
|
||||||
|
name: "[err]",
|
||||||
|
value: expanded,
|
||||||
|
variablesReference: 0
|
||||||
|
});
|
||||||
|
return submit();
|
||||||
|
}
|
||||||
|
strArr.push({
|
||||||
|
name: "[" + (arrIndex++) + "]",
|
||||||
|
value: expanded,
|
||||||
|
variablesReference: 0
|
||||||
|
});
|
||||||
|
addOne();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strArr.push({
|
||||||
|
name: "[err]",
|
||||||
|
value: expanded,
|
||||||
|
variablesReference: 0
|
||||||
|
});
|
||||||
|
submit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
this.sendErrorResponse(response, 14, `Could not expand variable: ` + e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
addOne();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
this.sendErrorResponse(response, 13, `Unimplemented variable request options: ` + JSON.stringify(varReq.options));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
response.body = {
|
||||||
|
variables: id
|
||||||
|
};
|
||||||
|
this.sendResponse(response);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
response.body = {
|
response.body = {
|
||||||
|
|
@ -398,6 +477,12 @@ export class MI2DebugSession extends DebugSession {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function prettyStringArray(strings: string[]) {
|
function prettyStringArray(strings) {
|
||||||
return strings.join(", ");
|
if (typeof strings == "object") {
|
||||||
|
if (strings.length !== undefined)
|
||||||
|
return strings.join(", ");
|
||||||
|
else
|
||||||
|
return JSON.stringify(strings);
|
||||||
|
}
|
||||||
|
else return strings;
|
||||||
}
|
}
|
||||||
|
|
@ -10,6 +10,8 @@ suite("GDB Value Expansion", () => {
|
||||||
assert.equal(expandValue(variableCreate, `5`), "5");
|
assert.equal(expandValue(variableCreate, `5`), "5");
|
||||||
assert.strictEqual(isExpandable(`"hello world!"`), 0);
|
assert.strictEqual(isExpandable(`"hello world!"`), 0);
|
||||||
assert.equal(expandValue(variableCreate, `"hello world!"`), `"hello world!"`);
|
assert.equal(expandValue(variableCreate, `"hello world!"`), `"hello world!"`);
|
||||||
|
assert.strictEqual(isExpandable(`0x7fffffffe956 "foobar"`), 0);
|
||||||
|
assert.equal(expandValue(variableCreate, `0x7fffffffe956 "foobar"`), `"foobar"`);
|
||||||
assert.strictEqual(isExpandable(`0x0`), 0);
|
assert.strictEqual(isExpandable(`0x0`), 0);
|
||||||
assert.equal(expandValue(variableCreate, `0x0`), "<nullptr>");
|
assert.equal(expandValue(variableCreate, `0x0`), "<nullptr>");
|
||||||
assert.strictEqual(isExpandable(`0x000000`), 0);
|
assert.strictEqual(isExpandable(`0x000000`), 0);
|
||||||
|
|
@ -29,6 +31,17 @@ suite("GDB Value Expansion", () => {
|
||||||
value: "d",
|
value: "d",
|
||||||
variablesReference: 0
|
variablesReference: 0
|
||||||
}]);
|
}]);
|
||||||
|
assert.strictEqual(isExpandable(`{[0] = 0x400730 "foo", [1] = 0x400735 "bar"}`), 1);
|
||||||
|
assert.deepEqual(expandValue(variableCreate, `{[0] = 0x400730 "foo", [1] = 0x400735 "bar"}`), [
|
||||||
|
{
|
||||||
|
name: "[0]",
|
||||||
|
value: "\"foo\"",
|
||||||
|
variablesReference: 0
|
||||||
|
}, {
|
||||||
|
name: "[1]",
|
||||||
|
value: "\"bar\"",
|
||||||
|
variablesReference: 0
|
||||||
|
}]);
|
||||||
assert.strictEqual(isExpandable(`{{a = b}}`), 1);
|
assert.strictEqual(isExpandable(`{{a = b}}`), 1);
|
||||||
assert.deepEqual(expandValue(variableCreate, `{{a = b}}`), [
|
assert.deepEqual(expandValue(variableCreate, `{{a = b}}`), [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue