From 0be3ad4f1bf0e679660409629e206818f20f6184 Mon Sep 17 00:00:00 2001 From: Bob Dubner <rdubner@symas.com> Date: Mon, 17 Aug 2020 18:30:18 -0400 Subject: [PATCH] Provide heirarchical display with _groupvalues= functionality --- CblGdbExt/CblGdb/src/backend/gdb_expansion.ts | 48 ++++++++++++++---- CblGdbExt/CblGdb/src/backend/mi2/mi2.ts | 31 ++++++++++-- CblGdbExt/CblGdb/src/mibase.ts | 26 +++++++++- CblGdbExt/samples/.gitignore | 0 CblGdbExt/samples/Makefile | 0 CblGdbExt/samples/Makefile.inc | 0 CblGdbExt/samples/ref_test_11/.gitignore | 3 ++ .../samples/ref_test_11/.vscode/launch.json | 29 +++++++++++ .../samples/ref_test_11/.vscode/tasks.json | 16 ++++++ CblGdbExt/samples/ref_test_11/Makefile | 3 ++ CblGdbExt/samples/ref_test_11/rtest.cbl | 50 +++++++++++++++++++ 11 files changed, 191 insertions(+), 15 deletions(-) mode change 100755 => 100644 CblGdbExt/samples/.gitignore mode change 100755 => 100644 CblGdbExt/samples/Makefile mode change 100755 => 100644 CblGdbExt/samples/Makefile.inc create mode 100644 CblGdbExt/samples/ref_test_11/.gitignore create mode 100755 CblGdbExt/samples/ref_test_11/.vscode/launch.json create mode 100644 CblGdbExt/samples/ref_test_11/.vscode/tasks.json create mode 100644 CblGdbExt/samples/ref_test_11/Makefile create mode 100644 CblGdbExt/samples/ref_test_11/rtest.cbl diff --git a/CblGdbExt/CblGdb/src/backend/gdb_expansion.ts b/CblGdbExt/CblGdb/src/backend/gdb_expansion.ts index 3f0605f..5632496 100644 --- a/CblGdbExt/CblGdb/src/backend/gdb_expansion.ts +++ b/CblGdbExt/CblGdb/src/backend/gdb_expansion.ts @@ -36,9 +36,25 @@ function GetImmediateGroupValue(str:string) : string { var nfound:number = str.indexOf(find_me); if( nfound == 0 ) { nfound += find_me.length; - while( nfound < str.length && str[nfound] != '"' ) { - retval += str[nfound]; + // We need to do a copy, keeping in mind that the possibility exists + // of backslashed escape sequences: + var escaped = false; + while( nfound < str.length ) { + let ch = str[nfound]; nfound += 1; + if( escaped ) { + retval += ch; + escaped = false; + continue; + } + if( ch == '\\' ){ + escaped = true; + continue; + } + if( ch == '"' ){ + break; + } + retval += ch } } return retval; @@ -46,27 +62,37 @@ function GetImmediateGroupValue(str:string) : string { export function expandValue(variableCreate: Function, value: string, root: string = "", extra: any = undefined): any { const parseCString = () => { + //console.log(`expandValue(1) ${value}`); value = value.trim(); - if (value[0] != '"' && value[0] != '\'') + if (value[0] != '"' && value[0] != '\'') { + console.log(" expandValue(2)","returning empty"); return ""; + } let stringEnd = 1; let inString = true; const charStr = value[0]; - let remaining = value.substr(1); let escaped = false; - while (inString) { - if (escaped) + let str = "";//value[0]; + while (inString && stringEnd < value.length) { + if (escaped) { escaped = false; - else if (remaining[0] == '\\') + str += value[stringEnd]; + } + else if (value[stringEnd] == '\\') { escaped = true; - else if (remaining[0] == charStr) + } + else if (value[stringEnd] == charStr) { + //str += value[stringEnd]; inString = false; - - remaining = remaining.substr(1); + } + else { + str += value[stringEnd]; + } stringEnd++; } - const str = value.substr(0, stringEnd).trim(); + str = str.trim(); value = value.substr(stringEnd).trim(); + //console.log(` expandValue(3): ${str} (${value})`); return str; }; diff --git a/CblGdbExt/CblGdb/src/backend/mi2/mi2.ts b/CblGdbExt/CblGdb/src/backend/mi2/mi2.ts index 3db8a10..a0c2427 100644 --- a/CblGdbExt/CblGdb/src/backend/mi2/mi2.ts +++ b/CblGdbExt/CblGdb/src/backend/mi2/mi2.ts @@ -417,15 +417,40 @@ export class MI2 extends EventEmitter implements IBackend { } retval += ch ; } - console.log("convert_mi_variables(2): ", retval); // DUBNERDEBUG + // The reader should be aware that the retval here is based very much on the output + // of GDB, in machine=interface mode, to a '-stack-list-variables --all-values' command. + // + // If a variable's contents require a backslash, the text string must be '\\' at that point. + // Likewise, '\"' is necessary to produce a single double-quote character. + // + // The following statement provides visibility to GDB-Python response + // to a 'print/m ?' command + //console.log("convert_mi_variables(2): ", retval); // DUBNERDEBUG + // The following statements allow for the injection of a hardcoded simulated "response" + // to such a command. Figuring out how to format the response wasn't easy. Nor was the + // process of debugging the public-domain debugger extension code so that it worked properly; + // this hard-coded injection proved very useful. + // // var nfound = retval.indexOf('['); // if(nfound != -1){ // var newr = retval.substr(0,nfound) // newr = newr + "[{name=\"L01\",value=\"{_groupvalue=\\\"Snap!\\\",fullname=\\\"RobertDubner\\\",L02={_groupvalue=\\\"Crackle!\\\",firstname = \\\"Robert\\\", lastname = \\\"Dubner\\\",L03={_groupvalue=\\\"Pop!\\\",firstname = \\\"Judy\\\", lastname = \\\"Ruderman\\\"}}}\"}]\n"; +// newr = newr + "[{name=\"L00L\",value=\"{_groupvalue=\\\"Sn\\\\\\\"ap!\\\",fullname=\\\"Robert\\\\\\\"Dubner\\\",L02={_groupvalue=\\\"Crackle!\\\",firstname = \\\"Robert\\\", lastname = \\\"\\\\\\\"Dubner\\\\\\\"\\\",L03={_groupvalue=\\\"Pop!\\\",firstname = \\\"Judy\\\", lastname = \\\"Ruderman\\\"}}}\"}]\n"; +// newr = newr + "[{name=\"L01\",value=\"===\\\">\\\\/<\\\"===\"}]\n"; // Produces ===">\/<"=== +// newr = newr + "[{name=\"L01\",value=\"\\\"===\\\">\\\\/<\\\"===,===\\\">\\\\/<\\\"===\"}]\n"; // Produces ===">\/<"=== +// // original newr = newr + "[{name="L00",value="\"Standalone\""},{name="slash1",value="\"***\\\"***\", ' ' <repeats 14 times>"},{name="slash2",value="\"\\\"**\\\"***\", ' ' <repeats 14 times>"},{name="slash3",value="\"***\\\"**\\\"\", ' ' <repeats 14 times>"},{name="slash4",value="\"\\\"**\\\"**\\\"\", ' ' <repeats 14 times>"},{name="slash5",value="\"***\\\"***},{***\\\"*** \""},{name="slash6",value="\"\\\"**\\\"***},{\\\"**\\\"*** \""},{name="slash7",value="\"***\\\"**\\\"{,}***\\\"**\\\" \""},{name="slash8",value="\"\\\"**\\\"**\\\"{,}\\\"**\\\"**\\\" \""},{name="L01",value="{fullname = \"RobertDubner\", L02 = {firstname = \"Robert\", lastname = \"Dubner\"}}"},{name="L01_2",value="{fullname = \"JudyRuderman\", L02 = {firstname = \"Judy\", lastname = \"Ruderman\"}}"}]"" +// newr = newr + "[{name=\"L00\",value=\"\\\"Standalone\\\"\"},{name=\"slash1\",value=\"\\\"***\\\\\\\"***\\\", ' ' <repeats 14 times>\"},{name=\"slash2\",value=\"\\\"\\\\\\\"**\\\\\\\"***\\\", ' ' <repeats 14 times>\"},{name=\"slash3\",value=\"\\\"***\\\\\\\"**\\\\\\\"\\\", ' ' <repeats 14 times>\"},{name=\"slash4\",value=\"\\\"\\\\\\\"**\\\\\\\"**\\\\\\\"\\\", ' ' <repeats 14 times>\"},{name=\"slash5\",value=\"\\\"***\\\\\\\"***},{***\\\\\\\"*** \\\"\"},{name=\"slash6\",value=\"\\\"\\\\\\\"**\\\\\\\"***},{\\\\\\\"**\\\\\\\"*** \\\"\"},{name=\"slash7\",value=\"\\\"***\\\\\\\"**\\\\\\\"{,}***\\\\\\\"**\\\\\\\" \\\"\"},{name=\"slash8\",value=\"\\\"\\\\\\\"**\\\\\\\"**\\\\\\\"{,}\\\\\\\"**\\\\\\\"**\\\\\\\" \\\"\"},{name=\"L01\",value=\"{fullname = \\\"RobertDubner\\\", L02 = {firstname = \\\"Robert\\\", lastname = \\\"Dubner\\\"}}\"},{name=\"L01_2\",value=\"{fullname = \\\"JudyRuderman\\\", L02 = {firstname = \\\"Judy\\\", lastname = \\\"Ruderman\\\"}}\"}]\n"; +// Original : +// [{name="L00",value="\"Standalone \""},{name="slash1",value="\"***\\\"***\""},{name="slash2",value="\"\\\"**\\\"***\""},{name="slash3",value="\"***\\\"**\\\"\""},{name="slash4",value="\"\\\"**\\\"**\\\"\""},{name="slash5",value="\"***\\\"***},{***\\\"*** \""},{name="slash6",value="\"\\\"**\\\"***},{\\\"**\\\"*** \""},{name="slash7",value="\"***\\\"**\\\"{,}***\\\"**\\\" \""},{name="slash8",value="\"\\\"**\\\"**\\\"{,}\\\"**\\\"**\\\" \""},{name="L01_1",value="{fullname = \"---\\\\^/---\", L02 = {firstname = \"/---\\\\^/---\\\\ \", lastname = \"\\\\---\\\\^/---/ \"}}"},{name="L01_2",value="{fullname = \"\\\\\\\"---\\\"\\\\^/\\\"---/\\\" \", L02 = {firstname = \"\\\\---\\\"\\\\^/\\\"---/\\\" \", lastname = \"\\\\\\\"---\\\"\\\\^/\\\"---/\\\" \"}}"}] +// With backslashes and double-quotes escaped: +// newr = newr + "[{name=\"L00\",value=\"\\\"Standalone \\\"\"},{name=\"slash1\",value=\"\\\"***\\\\\\\"***\\\"\"},{name=\"slash2\",value=\"\\\"\\\\\\\"**\\\\\\\"***\\\"\"},{name=\"slash3\",value=\"\\\"***\\\\\\\"**\\\\\\\"\\\"\"},{name=\"slash4\",value=\"\\\"\\\\\\\"**\\\\\\\"**\\\\\\\"\\\"\"},{name=\"slash5\",value=\"\\\"***\\\\\\\"***},{***\\\\\\\"*** \\\"\"},{name=\"slash6\",value=\"\\\"\\\\\\\"**\\\\\\\"***},{\\\\\\\"**\\\\\\\"*** \\\"\"},{name=\"slash7\",value=\"\\\"***\\\\\\\"**\\\\\\\"{,}***\\\\\\\"**\\\\\\\" \\\"\"},{name=\"slash8\",value=\"\\\"\\\\\\\"**\\\\\\\"**\\\\\\\"{,}\\\\\\\"**\\\\\\\"**\\\\\\\" \\\"\"},{name=\"L01_1\",value=\"{fullname = \\\"---\\\\\\\\^/---\\\", L02 = {firstname = \\\"/---\\\\\\\\^/---\\\\\\\\ \\\", lastname = \\\"\\\\\\\\---\\\\\\\\^/---/ \\\"}}\"},{name=\"L01_2\",value=\"{fullname = \\\"\\\\\\\\\\\\\\\"---\\\\\\\"\\\\\\\\^/\\\\\\\"---/\\\\\\\" \\\", L02 = {firstname = \\\"\\\\\\\\---\\\\\\\"\\\\\\\\^/\\\\\\\"---/\\\\\\\" \\\", lastname = \\\"\\\\\\\\\\\\\\\"---\\\\\\\"\\\\\\\\^/\\\\\\\"---/\\\\\\\" \\\"}}\"}]\n"; +// Original +// [{name="L01_1",value="{fullname = \"FULLNAME \", L02 = {firstname = \"FIRSTNAME \", lastname = \"LASTNAME \"}}"},{name="L01_2",value="{fullname = \"FULLNAME2 \", L02 = {firstname = \"FIRSTNAME2 \", lastname = \"LASTNAME2 \"}}"}] +//newr = newr + "[{name=\"L01_1\",value=\"{fullname = \\\"FULLNAME \\\", L02 = {firstname = \\\"FIRSTNAME \\\", lastname = \\\"LASTNAME \\\"}}\"},{name=\"L01_2\",value=\"{fullname = \\\"FULLNAME2 \\\", L02 = {firstname = \\\"FIRSTNAME2 \\\", lastname = \\\"LASTNAME2 \\\"}}\"}]\n"; +//newr = newr + "[{name=\"L00\",value=\"\\\"Standalone \\\"\"},{name=\"slash1\",value=\"\\\"***\\\\\\\"***\\\"\"},{name=\"slash2\",value=\"\\\"\\\\\\\"**\\\\\\\"***\\\"\"},{name=\"slash3\",value=\"\\\"***\\\\\\\"**\\\\\\\"\\\"\"},{name=\"slash4\",value=\"\\\"\\\\\\\"**\\\\\\\"**\\\\\\\"\\\"\"},{name=\"slash5\",value=\"\\\"***\\\\\\\"***},{***\\\\\\\"*** \\\"\"},{name=\"slash6\",value=\"\\\"\\\\\\\"**\\\\\\\"***},{\\\\\\\"**\\\\\\\"*** \\\"\"},{name=\"slash7\",value=\"\\\"***\\\\\\\"**\\\\\\\"{,}***\\\\\\\"**\\\\\\\" \\\"\"},{name=\"slash8\",value=\"\\\"\\\\\\\"**\\\\\\\"**\\\\\\\"{,}\\\\\\\"**\\\\\\\"**\\\\\\\" \\\"\"},{name=\"L01_1\",value=\"{_groupvalue=\\\"He\\\\\\\\\\\\\\\"llo\\\",fullname = \\\"---\\\\\\\\^/---\\\", L02 = {_groupvalue=\\\"\\\\\\\"D\\\\\\\\oo\\\\\\\"\\\\\\\\\\\\\\\"med\\\",firstname = \\\"/---\\\\\\\\^/---\\\\\\\\ \\\", lastname = \\\"\\\\\\\\---\\\\\\\\^/---/ \\\"}}\"},{name=\"L01_2\",value=\"{fullname = \\\"\\\\\\\\\\\\\\\"---\\\\\\\"\\\\\\\\^/\\\\\\\"---/\\\\\\\" \\\", L02 = {firstname = \\\"\\\\\\\\---\\\\\\\"\\\\\\\\^/\\\\\\\"---/\\\\\\\" \\\", lastname = \\\"\\\\\\\\\\\\\\\"---\\\\\\\"\\\\\\\\^/\\\\\\\"---/\\\\\\\" \\\"}}\"}]\n"; +// retval = newr ; // console.log("convert_mi_variables(3): ", newr); // DUBNERDEBUG -// retval = newr; // } - } } diff --git a/CblGdbExt/CblGdb/src/mibase.ts b/CblGdbExt/CblGdb/src/mibase.ts index 515158f..da3a898 100644 --- a/CblGdbExt/CblGdb/src/mibase.ts +++ b/CblGdbExt/CblGdb/src/mibase.ts @@ -22,6 +22,27 @@ class ExtendedVariable { const STACK_HANDLES_START = 1000; const VAR_HANDLES_START = 512 * 256 + 1000; +function DeEscape(vstr:string) { + let retval = ""; + let i = 0; + let escaped = false; + while( i<vstr.length ) { + let ch = vstr[i]; + i += 1; + if( escaped ) { + retval += ch; + escaped = false; + continue; + } + if( ch == '\\' ){ + escaped = true; + continue; + } + retval += ch; + } + return retval; +} + export class MI2DebugSession extends DebugSession { protected variableHandles = new Handles<string | VariableObject | ExtendedVariable>(VAR_HANDLES_START); protected variableHandlesReverse: { [id: string]: number } = {}; @@ -425,7 +446,10 @@ export class MI2DebugSession extends DebugSession { if(vstr == "") { vstr = '""' ; } - console.log("findOrCreateVariable(1)", vstr); //DUBNERDEBUG +// if( vstr && vstr[0] != '{' ){ +// vstr = DeEscape(vstr) ; +// } + //console.log("findOrCreateVariable(1)", vstr); //DUBNERDEBUG let expanded = expandValue(createVariable, `{${variable.name}=${vstr}`, "", variable.raw); if (expanded) { if (typeof expanded[0] == "string") diff --git a/CblGdbExt/samples/.gitignore b/CblGdbExt/samples/.gitignore old mode 100755 new mode 100644 diff --git a/CblGdbExt/samples/Makefile b/CblGdbExt/samples/Makefile old mode 100755 new mode 100644 diff --git a/CblGdbExt/samples/Makefile.inc b/CblGdbExt/samples/Makefile.inc old mode 100755 new mode 100644 diff --git a/CblGdbExt/samples/ref_test_11/.gitignore b/CblGdbExt/samples/ref_test_11/.gitignore new file mode 100644 index 0000000..67ffbc0 --- /dev/null +++ b/CblGdbExt/samples/ref_test_11/.gitignore @@ -0,0 +1,3 @@ +m +rtest.exe +rtest diff --git a/CblGdbExt/samples/ref_test_11/.vscode/launch.json b/CblGdbExt/samples/ref_test_11/.vscode/launch.json new file mode 100755 index 0000000..fb8d796 --- /dev/null +++ b/CblGdbExt/samples/ref_test_11/.vscode/launch.json @@ -0,0 +1,29 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Build ${file} with cobc/cobst, debug with debugServer", + "type": "node", + "request": "launch", + "skipFiles": ["<node_internals>/**"], + "preLaunchTask": "make", + "program": "${workspaceRoot}/rtest", + "cwd": "${workspaceFolder}", + "arguments": "", + "debugServer": 4711 + }, + { + "name": "cobc/cobst build and debug", + "type": "cbl-gdb", + "request": "launch", + "preLaunchTask": "make", + "program": "${workspaceFolder}/rtest", + "cwd": "${workspaceFolder}", + "arguments": "" + } + + ] +} \ No newline at end of file diff --git a/CblGdbExt/samples/ref_test_11/.vscode/tasks.json b/CblGdbExt/samples/ref_test_11/.vscode/tasks.json new file mode 100644 index 0000000..076b506 --- /dev/null +++ b/CblGdbExt/samples/ref_test_11/.vscode/tasks.json @@ -0,0 +1,16 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "make", + "type": "shell", + "command": "make", + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} \ No newline at end of file diff --git a/CblGdbExt/samples/ref_test_11/Makefile b/CblGdbExt/samples/ref_test_11/Makefile new file mode 100644 index 0000000..158b2c0 --- /dev/null +++ b/CblGdbExt/samples/ref_test_11/Makefile @@ -0,0 +1,3 @@ +project=rtest + +include ../Makefile.inc \ No newline at end of file diff --git a/CblGdbExt/samples/ref_test_11/rtest.cbl b/CblGdbExt/samples/ref_test_11/rtest.cbl new file mode 100644 index 0000000..dea80a6 --- /dev/null +++ b/CblGdbExt/samples/ref_test_11/rtest.cbl @@ -0,0 +1,50 @@ + ID DIVISION. + PROGRAM-ID. RTEST. + DATA DIVISION. + WORKING-STORAGE SECTION. + 77 slash1 PICTURE X(20) VALUE '***"***'. + 77 slash2 PICTURE X(20) VALUE '"**"***'. + 77 slash3 PICTURE X(20) VALUE '***"**"'. + 77 slash4 PICTURE X(20) VALUE '"**"**"'. + 77 slash5 PICTURE X(20) VALUE '***"***,***"***'. + 77 slash6 PICTURE X(20) VALUE '"**"***,"**"***'. + 77 slash7 PICTURE X(20) VALUE '***"**",***"**"'. + 77 slash8 PICTURE X(20) VALUE '"**"**","**"**"'. + + 01 standalone PIC X(10) value "standalone". + 01 bob . + 02 firstname PIC X(6) value "Robert". + 02 lastname PIC X(6) value "Dubner". + 02 placeandyear. + 03 place PIC X(8) value "Brooklyn". + 03 year PIC 9(4) value 1953. + 02 scrambles . + 03 scram1 PIC X(9) value "---\^/---". + 03 scram2 PIC X(9) value "--""\^/""--". + 01 judy . + 02 firstname PIC X(4) value "Judy". + 02 lastname PIC X(8) value "Ruderman". + 02 placeandyear. + 03 place PIC X(8) value "Queens". + 03 year PIC 9(4) value 1957. + PROCEDURE DIVISION. + display slash1. + display slash2. + display slash3. + display slash4. + display slash5. + display slash6. + display slash7. + display slash8. + + display standalone. + display firstname of bob. + display lastname of bob. + display place of bob. + display year of bob. + display firstname of judy. + display lastname of judy. + display place of judy. + display year of judy. + STOP RUN. + END PROGRAM RTEST. -- GitLab