Fixed C/C++ argument list & char*[]

Fix #69 (hihi Kappa)
This commit is contained in:
WebFreak001 2016-08-13 13:34:34 +02:00
commit 5fc8765678
5 changed files with 144 additions and 33 deletions

View file

@ -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 {

View file

@ -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));

View file

@ -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);

View file

@ -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;
} }

View file

@ -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}}`), [
{ {