Cosmetic changes for specifying conditions in breakpoints.

Add the 'if' word to the dialogs.
Parse the breakpoints table more effieciently.
This commit is contained in:
Ernie Pasveer
2023-11-24 13:11:49 -06:00
parent f3e454003d
commit c84dd60a7e
9 changed files with 207 additions and 46 deletions
+1 -1
View File
@@ -161,7 +161,7 @@
<item row="0" column="2">
<widget class="QCheckBox" name="conditionalCheckBox">
<property name="text">
<string>Conditional</string>
<string>Condition if:</string>
</property>
</widget>
</item>
+31 -19
View File
@@ -106,32 +106,44 @@ void SeerBreakpointsBrowserWidget::handleText (const QString& text) {
// }
//
//qDebug().noquote() << bkpt_list;
QString newtext = Seer::filterEscapes(text); // Filter escaped characters.
QString body_text = Seer::parseFirst(newtext, "body=", '[', ']', false);
//qDebug() << body_text;
QString body_text = Seer::parseFirst(text, "body=", '[', ']', false);
if (body_text != "") {
QStringList bkpt_list = Seer::parse(newtext, "bkpt=", '{', '}', false);
for ( const auto& bkpt_text : bkpt_list ) {
QString number_text = Seer::parseFirst(bkpt_text, "number=", '"', '"', false);
QString type_text = Seer::parseFirst(bkpt_text, "type=", '"', '"', false);
QString disp_text = Seer::parseFirst(bkpt_text, "disp=", '"', '"', false);
QString enabled_text = Seer::parseFirst(bkpt_text, "enabled=", '"', '"', false);
QString addr_text = Seer::parseFirst(bkpt_text, "addr=", '"', '"', false);
QString func_text = Seer::parseFirst(bkpt_text, "func=", '"', '"', false);
QString file_text = Seer::parseFirst(bkpt_text, "file=", '"', '"', false);
QString fullname_text = Seer::parseFirst(bkpt_text, "fullname=", '"', '"', false);
QString line_text = Seer::parseFirst(bkpt_text, "line=", '"', '"', false);
QString thread_groups_text = Seer::parseFirst(bkpt_text, "thread-groups=", '[', ']', false);
QString cond_text = Seer::parseFirst(bkpt_text, "cond=", '"', '"', false);
QString times_text = Seer::parseFirst(bkpt_text, "times=", '"', '"', false);
QString ignore_text = Seer::parseFirst(bkpt_text, "ignore=", '"', '"', false);
QString script_text = Seer::parseFirst(bkpt_text, "script=", '{', '}', false);
QString original_location_text = Seer::parseFirst(bkpt_text, "original-location=", '"', '"', false);
//
// A different way (better?) of parsing the table output
//
// Divide test into a list, delimited by a ','.
// Then morph that list into a map, delimited by a '='.
// Remove bookends.
//
QStringList items = Seer::parseCommaList(bkpt_text);
QMap<QString,QString> keyValueMap = Seer::createKeyValueMap(items, '=');
QString number_text = Seer::filterBookends(keyValueMap["number"], '"', '"');
QString type_text = Seer::filterBookends(keyValueMap["type"], '"', '"');
QString disp_text = Seer::filterBookends(keyValueMap["disp"], '"', '"');
QString enabled_text = Seer::filterBookends(keyValueMap["enabled"], '"', '"');
QString addr_text = Seer::filterBookends(keyValueMap["addr"], '"', '"');
QString func_text = Seer::filterBookends(keyValueMap["func"], '"', '"');
QString file_text = Seer::filterBookends(keyValueMap["file"], '"', '"');
QString fullname_text = Seer::filterBookends(keyValueMap["fullname"], '"', '"');
QString line_text = Seer::filterBookends(keyValueMap["line"], '"', '"');
QString thread_groups_text = Seer::filterBookends(keyValueMap["thread-groups"], '[', ']');
QString cond_text = Seer::filterBookends(keyValueMap["cond"], '"', '"');
QString times_text = Seer::filterBookends(keyValueMap["times"], '"', '"');
QString ignore_text = Seer::filterBookends(keyValueMap["ignore"], '"', '"');
QString script_text = Seer::filterBookends(keyValueMap["script"], '{', '}');
QString original_location_text = Seer::filterBookends(keyValueMap["original-location"], '"', '"');
// Only look for 'breakpoint' type break points.
if (type_text != "breakpoint") {
@@ -334,7 +346,7 @@ void SeerBreakpointsBrowserWidget::handleConditionToolButton () {
// Get the condition text.
bool ok;
QString condition = QInputDialog::getText(this, "Seer", "Enter the condition for this breakpoint.\nA blank condition will remove an existing one.", QLineEdit::Normal, items.front()->text(10), &ok);
QString condition = QInputDialog::getText(this, "Seer", "Enter the condition for this breakpoint.\nA blank condition will remove an existing one.\n\nif:", QLineEdit::Normal, items.front()->text(10), &ok);
if (ok == false) {
return;
+110 -1
View File
@@ -297,6 +297,102 @@ namespace Seer {
return list;
}
QStringList parseCommaList (const QString& str) {
//
// number="2",type="breakpoint",disp="keep",enabled="y",addr="0x00000000004016cd",func="main(int, char**)",file="hellofibonacci.cpp",fullname="/nas/erniep/Development/seer/tests/hellofibonacci/hellofibonacci.cpp",line="34",thread-groups=["i1"],cond="$_streq(s.c_str(), "21")",times="0",original-location="hellofibonacci.cpp:34"
//
// returns...
//
// number="2"
// type="breakpoint"
// disp="keep"
// enabled="y"
// addr="0x00000000004016cd"
// func="main(int char**)"
// file="hellofibonacci.cpp"
// fullname="/nas/erniep/Development/seer/tests/hellofibonacci/hellofibonacci.cpp"
// line="34"
// thread-groups=["i1"]
// cond="$_streq(s.c_str() "21")"
// times="0"
// original-location="hellofibonacci.cpp:34"
//
QStringList list;
int index = 0;
int state = 0;
int start = 0;
int end = 0;
bool inquotes = false;
int bracketlevel = 0;
while (index < str.length()) {
// Handle start of field.
if (state == 0) { // Start of field.
start = index;
end = index;
state = 1; // Look for end of field (a command or eol).
continue;
}
// Handle end of field.
if (state == 1) {
// Handle """
if (str[index] == '"') {
if (inquotes == false) {
inquotes = true;
}else{
inquotes = false;
}
index++; continue;
}
// Handle ","
if (str[index] == ',') {
if (inquotes) {
index++; continue;
}
// Extract field, only if the bracket level is at zero.
// Otherwise, continue.
if (bracketlevel == 0) {
end = index;
QString field = str.mid(start, end-start);
list.append(field.trimmed());
state = 0; // Look for the next field.
}
index++; continue;
}
// Handle any other character.
index++; continue;
}
qDebug() << "Bad state!";
index++; continue;
}
// Handle last field, if any.
if (state == 1) {
end = index;
QString field = str.mid(start, end-start);
list.append(field.trimmed());
}
return list;
}
QStringList parseCommaList (const QString& str, QChar startBracket, QChar endBracket) {
// name = "Pasveer, Ernie", age = 60, salary = 0.25, location = {city = "Houston", state = "Texas", zip = 77063}
@@ -402,11 +498,24 @@ namespace Seer {
return list;
}
QMap<QString,QString> createKeyValueMap (const QStringList& list, QChar separator) {
QMap<QString,QString> map;
for (const auto& i : list) {
QStringPair pair = parseNameValue(i, separator);
map[pair.first] = pair.second;
}
return map;
}
//
//
//
QStringPair parseNameValue (const QString& str, QChar separator) {
QStringPair parseNameValue (const QString& str, QChar separator) {
// name = "Pasveer, Ernie"
//
+25 -22
View File
@@ -2,35 +2,38 @@
#include "QStringPair.h"
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QMap>
namespace Seer {
QString version ();
QString version ();
QString filterEscapes (const QString& str, bool handleCR = true);
QStringList filterEscapes (const QStringList& strings, bool handleCR = true);
QString expandTabs (const QString& str, int tabwidth, bool morph);
QString expandEnv (const QString& str, bool* ok = nullptr);
QStringList parse (const QString& str, const QString& search, QChar startBracket, QChar endBracket, bool includeSearch);
QString parseFirst (const QString& str, const QString& search, QChar startBracket, QChar endBracket, bool includeSearch);
QString parseFirst (const QString& str, const QString& search, bool includeSearch);
bool hasBookends (const QString& str, QChar startBracket, QChar endBracket);
QString filterBookends (const QString& str, QChar startBracket, QChar endBracket);
QStringList filterBookends (const QStringList& strings, QChar startBracket, QChar endBracket);
QStringList parseCommaList (const QString& str, QChar startBracket, QChar endBracket);
QStringPair parseNameValue (const QString& str, QChar separator);
QString quoteChars (const QString& str, const QString& chars);
QStringList quoteChars (const QStringList& strings, const QString& chars);
QString varObjParent (const QString& str);
bool matchesWildcard (const QStringList& regexpatterns, const QString& string);
QString filterEscapes (const QString& str, bool handleCR = true);
QStringList filterEscapes (const QStringList& strings, bool handleCR = true);
QString expandTabs (const QString& str, int tabwidth, bool morph);
QString expandEnv (const QString& str, bool* ok = nullptr);
QStringList parse (const QString& str, const QString& search, QChar startBracket, QChar endBracket, bool includeSearch);
QString parseFirst (const QString& str, const QString& search, QChar startBracket, QChar endBracket, bool includeSearch);
QString parseFirst (const QString& str, const QString& search, bool includeSearch);
bool hasBookends (const QString& str, QChar startBracket, QChar endBracket);
QString filterBookends (const QString& str, QChar startBracket, QChar endBracket);
QStringList filterBookends (const QStringList& strings, QChar startBracket, QChar endBracket);
QStringList parseCommaList (const QString& str);
QStringList parseCommaList (const QString& str, QChar startBracket, QChar endBracket);
QMap<QString,QString> createKeyValueMap (const QStringList& list, QChar separator);
QStringPair parseNameValue (const QString& str, QChar separator);
QString quoteChars (const QString& str, const QString& chars);
QStringList quoteChars (const QStringList& strings, const QString& chars);
QString varObjParent (const QString& str);
bool matchesWildcard (const QStringList& regexpatterns, const QString& string);
int createID ();
int createID ();
unsigned char ebcdicToAscii (unsigned char byte);
unsigned char ucharToAscii (unsigned char byte);
unsigned char ebcdicToAscii (unsigned char byte);
unsigned char ucharToAscii (unsigned char byte);
int typeBytes (const QString& type);
int typeBytes (const QString& type);
bool readFile (const QString& filename, QStringList& lines);
bool readFile (const QString& filename, QStringList& lines);
}
+2
View File
@@ -0,0 +1,2 @@
gdbmi_condition
core*
+10
View File
@@ -0,0 +1,10 @@
.PHONY: all
all: gdbmi_condition
gdbmi_condition: gdbmi_condition.cpp
g++ -g -o gdbmi_condition gdbmi_condition.cpp
.PHONY: clean
clean:
rm -f gdbmi_condition gdbmi_condition.o
+20
View File
@@ -0,0 +1,20 @@
#include <iostream>
#include <string>
int main (int argc, char* argv[]) {
std::string name = "";
name = "ernie";
// Create the breakpoint with a string condition.
//
// -break-insert -c 'name.c_str() == "ernie"' gdbmi_condition.cpp:16 // Failed parsing.
// -break-insert -c '$_streq(name.c_str(), "ernie")' gdbmi_condition.cpp:16 // Failed parsing.
// -break-insert -c 'strcmp("xxxxx", name.c_str() == 0' gdbmi_condition.cpp:16 // Is accepted but breaks eventhough strings are different.
std::cout << "Name is: " << name << std::endl;
return 0;
}
+2 -2
View File
@@ -1,3 +1,3 @@
break -source /nas/erniep/Development/seer/tests/hellofibonacci/hellofibonacci.cpp -line 23
break -source /nas/erniep/Development/seer/tests/hellofibonacci/hellofibonacci.cpp -line 29
condition $bpnum nextTerm > 10
break hellofibonacci.cpp:34
condition $bpnum $_streq(s.c_str(), "21")
+6 -1
View File
@@ -26,7 +26,12 @@ int main (int argc, char* argv[]) {
nextTerm = t1 + t2;
while (nextTerm <= n) {
std::cout << nextTerm << ", ";
std::string s = "";
s = std::to_string(nextTerm);
std::cout << s << ", ";
t1 = t2;
t2 = nextTerm;
nextTerm = t1 + t2;