diff --git a/src/SeerBreakpointCreateDialog.ui b/src/SeerBreakpointCreateDialog.ui index 0ee80482..bf848933 100644 --- a/src/SeerBreakpointCreateDialog.ui +++ b/src/SeerBreakpointCreateDialog.ui @@ -161,7 +161,7 @@ - Conditional + Condition if: diff --git a/src/SeerBreakpointsBrowserWidget.cpp b/src/SeerBreakpointsBrowserWidget.cpp index f76805e3..444ffb46 100644 --- a/src/SeerBreakpointsBrowserWidget.cpp +++ b/src/SeerBreakpointsBrowserWidget.cpp @@ -106,32 +106,44 @@ void SeerBreakpointsBrowserWidget::handleText (const QString& text) { // } // - QString newtext = Seer::filterEscapes(text); // Filter escaped characters. + //qDebug().noquote() << bkpt_list; - QString body_text = Seer::parseFirst(newtext, "body=", '[', ']', false); + QString newtext = Seer::filterEscapes(text); // Filter escaped characters. - //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 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; diff --git a/src/SeerUtl.cpp b/src/SeerUtl.cpp index 415b37ef..046d148e 100644 --- a/src/SeerUtl.cpp +++ b/src/SeerUtl.cpp @@ -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 createKeyValueMap (const QStringList& list, QChar separator) { + + QMap 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" // diff --git a/src/SeerUtl.h b/src/SeerUtl.h index c7b392a0..1ddbfea1 100644 --- a/src/SeerUtl.h +++ b/src/SeerUtl.h @@ -2,35 +2,38 @@ #include "QStringPair.h" #include #include +#include namespace Seer { - 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); - - int createID (); - - unsigned char ebcdicToAscii (unsigned char byte); - unsigned char ucharToAscii (unsigned char byte); - - int typeBytes (const QString& type); - - bool readFile (const QString& filename, QStringList& lines); + 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); + QStringList parseCommaList (const QString& str, QChar startBracket, QChar endBracket); + QMap 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 (); + + unsigned char ebcdicToAscii (unsigned char byte); + unsigned char ucharToAscii (unsigned char byte); + + int typeBytes (const QString& type); + + bool readFile (const QString& filename, QStringList& lines); } diff --git a/tests/gdbmi_condition/.gitignore b/tests/gdbmi_condition/.gitignore new file mode 100644 index 00000000..0bfbda5e --- /dev/null +++ b/tests/gdbmi_condition/.gitignore @@ -0,0 +1,2 @@ +gdbmi_condition +core* diff --git a/tests/gdbmi_condition/Makefile b/tests/gdbmi_condition/Makefile new file mode 100644 index 00000000..9d31959e --- /dev/null +++ b/tests/gdbmi_condition/Makefile @@ -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 + diff --git a/tests/gdbmi_condition/gdbmi_condition.cpp b/tests/gdbmi_condition/gdbmi_condition.cpp new file mode 100644 index 00000000..4c6b4976 --- /dev/null +++ b/tests/gdbmi_condition/gdbmi_condition.cpp @@ -0,0 +1,20 @@ +#include +#include + +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; +} + diff --git a/tests/hellofibonacci/breakpoints.seer b/tests/hellofibonacci/breakpoints.seer index b9fcb86d..b41d9f37 100644 --- a/tests/hellofibonacci/breakpoints.seer +++ b/tests/hellofibonacci/breakpoints.seer @@ -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") diff --git a/tests/hellofibonacci/hellofibonacci.cpp b/tests/hellofibonacci/hellofibonacci.cpp index 152c486f..18362469 100644 --- a/tests/hellofibonacci/hellofibonacci.cpp +++ b/tests/hellofibonacci/hellofibonacci.cpp @@ -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;