Skip to content

Commit 6a658d7

Browse files
committed
solve the problem of failed parsing of std containers, add test suite
1 parent d840528 commit 6a658d7

File tree

4 files changed

+124
-7
lines changed

4 files changed

+124
-7
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Versioning].
2121
- New `frameFilters` option for GDB that allows using custom frame filters,
2222
enabled by default ([@JacquesLucke])
2323
- Suppress error for hover as the user may just play with the mouse ([@oltolm]).
24+
- solve the problem of failed parsing of containers ([@henryriley0])
2425

2526
## [0.27.0] - 2024-02-07
2627

src/backend/gdb_expansion.ts

+27-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { VariableObject } from "./backend";
22
import { MINode } from "./mi_parse";
33

4-
const resultRegex = /^([a-zA-Z_\-][a-zA-Z0-9_\-]*|\[\d+\])\s*=\s*/;
5-
const variableRegex = /^[a-zA-Z_\-][a-zA-Z0-9_\-]*/;
4+
const resultRegex = /^([a-zA-Z_\-][a-zA-Z0-9_\-<> :(),]*|\[\d+\])\s*=\s*/;
5+
const variableRegex = /^[a-zA-Z_\-\'\(][a-zA-Z0-9_\-\>\ \\\'\)\:]*/;
66
const errorRegex = /^\<.+?\>/;
77
const referenceStringRegex = /^(0x[0-9a-fA-F]+\s*)"/;
88
const referenceRegex = /^0x[0-9a-fA-F]+/;
@@ -105,14 +105,18 @@ export function expandValue(variableCreate: (arg: VariableObject | string, optio
105105
const eqPos = value.indexOf("=");
106106
const newValPos1 = value.indexOf("{");
107107
const newValPos2 = value.indexOf(",");
108+
const newValPos3 = value.indexOf("}");
108109
let newValPos = newValPos1;
109110
if (newValPos2 != -1 && newValPos2 < newValPos1)
110111
newValPos = newValPos2;
111-
if (newValPos != -1 && eqPos > newValPos || eqPos == -1) { // is value list
112+
if (newValPos != -1 && eqPos > newValPos || eqPos == -1 || eqPos > newValPos3 || value.startsWith("std::")) { // is value list
112113
const values = [];
113114
stack.push("[0]");
114115
let val = parseValue();
115116
stack.pop();
117+
if(typeof val == "string" && val.endsWith('>')){
118+
val = val.substring(0, val.length - 2);
119+
}
116120
values.push(createValue("[0]", val));
117121
const remaining = value;
118122
let i = 0;
@@ -191,18 +195,26 @@ export function expandValue(variableCreate: (arg: VariableObject | string, optio
191195
return parseCString();
192196
else if (value[0] == '{')
193197
return parseTupleOrList();
198+
else if(value.startsWith("std::")){
199+
const eqPos = value.indexOf("=");
200+
value = value.substring(eqPos + 2);
201+
return parseValue();
202+
}
194203
else
195204
return parsePrimitive();
196205
};
197206

198207
parseResult = (pushToStack: boolean = false) => {
199-
value = value.trim();
200-
value = value.replace(/^static /, "");
208+
value = value.replace(/^</, "").trim().replace(/^static /, "");
201209
const variableMatch = resultRegex.exec(value);
202210
if (!variableMatch)
203211
return undefined;
204212
value = value.substring(variableMatch[0].length).trim();
205-
const name = variable = variableMatch[1];
213+
let name = variable = variableMatch[1].trim();
214+
const tmpName = name.split(" ");
215+
if(tmpName.length > 1 && !name.includes("anonymous union") && !name.includes(',')){
216+
name = tmpName[tmpName.length - 1];
217+
}
206218
if (pushToStack)
207219
stack.push(variable);
208220
const val = parseValue();
@@ -231,6 +243,15 @@ export function expandValue(variableCreate: (arg: VariableObject | string, optio
231243
ref = variableCreate(getNamespace(name));
232244
val = "...";
233245
}
246+
value = value.trim();
247+
if (value[0] == ','){
248+
let tmp = value;
249+
tmp = tmp.substring(1).trim();
250+
if(tmp.startsWith("<No data fields>")){
251+
value = tmp.replace(/^<No data fields>/, "");
252+
}
253+
}
254+
234255
return {
235256
name: name,
236257
value: val,

src/mibase.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,14 @@ export class MI2DebugSession extends DebugSession {
537537
// TODO: this evaluates on an (effectively) unknown thread for multithreaded programs.
538538
variable = await this.miDebugger.evalExpression(JSON.stringify(id), 0, 0);
539539
try {
540-
let expanded = expandValue(createVariable, variable.result("value"), id, variable);
540+
let variableValue = variable.result("value");
541+
const pattern = /'([^']*)' <repeats (\d+) times>/g;
542+
variableValue = variableValue.replace(pattern, (_: any, char: string, count: string) => {
543+
const repeatCount = parseInt(count, 10) + 1;
544+
const repeatedArray = Array(repeatCount).fill(char);
545+
return `{${repeatedArray.map(item => `'${item}'`).join(', ')}}`;
546+
});
547+
let expanded = expandValue(createVariable, variableValue, id, variable);
541548
if (!expanded) {
542549
this.sendErrorResponse(response, 2, `Could not expand variable`);
543550
} else {

src/test/unit/gdb_expansion.test.ts

+88
Original file line numberDiff line numberDiff line change
@@ -304,4 +304,92 @@ suite("GDB Value Expansion", () => {
304304
{ name: "floatval2", value: "234.45", variablesReference: 0 }
305305
]);
306306
});
307+
test("std container values", () => {
308+
let node = `std::vector of length 4, capacity 6 = {1, 2, 3, 4}`;
309+
let variables = expandValue(variableCreate, node);
310+
assert.strictEqual(variables[3].value, `4`);
311+
node = `std::deque with 7 elements = {0, 1, 2, 3, 4, 5, 6}`;
312+
variables = expandValue(variableCreate, node);
313+
assert.strictEqual(variables[6].value, `6`);
314+
node = `std::__cxx11::list = {[0] = 6, [1] = 7, [2] = 8, [3] = 9, [4] = 10}`;
315+
variables = expandValue(variableCreate, node);
316+
assert.strictEqual(variables[4].value, `10`);
317+
node = `std::vector of length 4, capacity 6 = {std::vector of length 3, capacity 3 = {1, 2, 3}, std::vector of length 3, capacity 3 = {4, 5, 6}, std::vector of length 3, capacity 3 = {7, 8, 9}, std::vector of length 4, capacity 4 = {1, 2, 3, 4}}`;
318+
variables = expandValue(variableCreate, node);
319+
assert.strictEqual(variables[3].variablesReference.expanded[3].value, `4`);
320+
node = `std::deque with 3 elements = {std::deque with 2 elements = {10, 20}, std::deque with 2 elements = {30, 40}, std::deque with 7 elements = {0, 1, 2, 3, 4, 5, 6}}`;
321+
variables = expandValue(variableCreate, node);
322+
assert.strictEqual(variables[2].variablesReference.expanded[6].value, `6`);
323+
node = `std::__cxx11::list = {[0] = std::__cxx11::list = {[0] = 11, [1] = 12}, [1] = std::__cxx11::list = {[0] = 13, [1] = 14}, [2] = std::__cxx11::list = {[0] = 6, [1] = 7, [2] = 8, [3] = 9, [4] = 10}}`;
324+
variables = expandValue(variableCreate, node);
325+
assert.strictEqual(variables[2].variablesReference.expanded[4].value, `10`);
326+
node = `std::forward_list = {[0] = 0, [1] = 1, [2] = 2, [3] = 3}`;
327+
variables = expandValue(variableCreate, node);
328+
assert.strictEqual(variables[3].value, `3`);
329+
node = `std::set with 5 elements = {[0] = 1, [1] = 2, [2] = 3, [3] = 4, [4] = 5}`;
330+
variables = expandValue(variableCreate, node);
331+
assert.strictEqual(variables[4].value, `5`);
332+
node = `std::multiset with 6 elements = {[0] = 1, [1] = 2, [2] = 2, [3] = 2, [4] = 3, [5] = 4}`;
333+
variables = expandValue(variableCreate, node);
334+
assert.strictEqual(variables[5].value, `4`);
335+
node = `std::map with 3 elements = {[1] = \"one\", [2] = \"two\", [3] = \"three\"}`;
336+
variables = expandValue(variableCreate, node);
337+
assert.strictEqual(variables[2].value, `"three"`);
338+
node = `std::multimap with 3 elements = {[1] = \"one\", [2] = \"two\", [2] = \"another two\"}`;
339+
variables = expandValue(variableCreate, node);
340+
assert.strictEqual(variables[2].value, `"another two"`);
341+
node = `std::unordered_set with 5 elements = {[0] = 5, [1] = 2, [2] = 3, [3] = 1, [4] = 4}`;
342+
variables = expandValue(variableCreate, node);
343+
assert.strictEqual(variables[4].value, `4`);
344+
node = `std::unordered_multiset with 6 elements = {[0] = 1, [1] = 2, [2] = 2, [3] = 2, [4] = 3, [5] = 4}`;
345+
variables = expandValue(variableCreate, node);
346+
assert.strictEqual(variables[5].value, `4`);
347+
node = `std::unordered_map with 3 elements = {[3] = \"three\", [1] = \"one\", [2] = \"two\"}`;
348+
variables = expandValue(variableCreate, node);
349+
assert.strictEqual(variables[2].value, `"two"`);
350+
node = `std::unordered_multimap with 3 elements = {[2] = \"another two\", [2] = \"two\", [1] = \"one\"}`;
351+
variables = expandValue(variableCreate, node);
352+
assert.strictEqual(variables[2].value, `"one"`);
353+
node = `std::stack wrapping: std::deque with 2 elements = {1, 2}`;
354+
variables = expandValue(variableCreate, node);
355+
assert.strictEqual(variables[1].value, `2`);
356+
node = `std::queue wrapping: std::deque with 2 elements = {1, 2}`;
357+
variables = expandValue(variableCreate, node);
358+
assert.strictEqual(variables[1].value, `2`);
359+
node = `std::priority_queue wrapping: std::vector of length 3, capacity 4 = {4, 1, 3}`;
360+
variables = expandValue(variableCreate, node);
361+
assert.strictEqual(variables[2].value, `3`);
362+
node = `std::bitset = {[0] = 1, [2] = 1, [4] = 1, [6] = 1, [7] = 1}`;
363+
variables = expandValue(variableCreate, node);
364+
assert.strictEqual(variables[3].value, `1`);
365+
node = `{_M_elems = {1, 2, 3}}`;
366+
variables = expandValue(variableCreate, node);
367+
assert.strictEqual(variables[0].variablesReference.expanded[2].value, `3`);
368+
node = `std::unique_ptr<int> = {get() = 0x5555555d7d20}`;
369+
variables = expandValue(variableCreate, node);
370+
assert.strictEqual(variables[0].name, `get()`);
371+
assert.strictEqual(variables[0].value, `Object@*0x5555555d7d20`);
372+
node = `std::unique_ptr<int []> = {get() = 0x5555555d7d40}`;
373+
variables = expandValue(variableCreate, node);
374+
assert.strictEqual(variables[0].name, `get()`);
375+
assert.strictEqual(variables[0].value, `Object@*0x5555555d7d40`);
376+
node = `std::shared_ptr<int> (use count 1, weak count 1) = {get() = 0x5555555d7d70}`;
377+
variables = expandValue(variableCreate, node);
378+
assert.strictEqual(variables[0].name, `get()`);
379+
assert.strictEqual(variables[0].value, `Object@*0x5555555d7d70`);
380+
node = `{<std::__atomic_base<int>> = {static _S_alignment = 4, _M_i = 0}, <No data fields>}`;
381+
variables = expandValue(variableCreate, node);
382+
assert.strictEqual(variables[0].name, `std::__atomic_base<int>>`);
383+
assert.strictEqual(variables[0].variablesReference.expanded[1].name, `_M_i`);
384+
assert.strictEqual(variables[0].variablesReference.expanded[1].value, `0`);
385+
node = `{<std::__mutex_base> = {_M_mutex = {__data = {__lock = 0, __count = 0, __owner = 0, __nusers = 0, __kind = 0, __spins = 0, __elision = 0, __list = {__prev = 0x0, __next = 0x0}}, __size = '\\000' <repeats 39 times>, __align = 0}}, <No data fields>}`;
386+
variables = expandValue(variableCreate, node);
387+
assert.strictEqual(variables[0].variablesReference.expanded[0].variablesReference.expanded[0].variablesReference.expanded[7].variablesReference.expanded[1].name, `__next`);
388+
assert.strictEqual(variables[0].variablesReference.expanded[0].variablesReference.expanded[0].variablesReference.expanded[7].variablesReference.expanded[1].value, `<nullptr>`);
389+
node = `{static icase = <optimized out>, static nosubs = <optimized out>, static optimize = <optimized out>, static collate = <optimized out>, static ECMAScript = (unknown: 16), static basic = <optimized out>, static extended = <optimized out>, static awk = <optimized out>, static grep = <optimized out>, static egrep = <optimized out>, _M_flags = (unknown: 16), _M_loc = {static none = 0, static ctype = 1, static numeric = 2, static collate = 4, static time = 8, static monetary = 16, static messages = 32, static all = 63, _M_impl = 0x7ffff7fa8ce0, static _S_classic = <optimized out>, static _S_global = <optimized out>, static _S_categories = <optimized out>, static _S_once = <optimized out>, static _S_twinned_facets = <optimized out>}, _M_automaton = std::shared_ptr<const std::__detail::_NFA<std::__cxx11::regex_traits<char> >> (use count 1, weak count 0) = {get() = 0x5555555d81b0}}`;
390+
variables = expandValue(variableCreate, node);
391+
assert.strictEqual(variables[12].name, `_M_automaton`);
392+
assert.strictEqual(variables[12].variablesReference.expanded[0].value, `Object@*0x5555555d81b0`);
393+
394+
});
307395
});

0 commit comments

Comments
 (0)