Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cosmetic changes for specifying conditions in breakpoints. #186

Merged
merged 1 commit into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/SeerBreakpointCreateDialog.ui
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
50 changes: 31 additions & 19 deletions src/SeerBreakpointsBrowserWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<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") {
Expand Down Expand Up @@ -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;
Expand Down
111 changes: 110 additions & 1 deletion src/SeerUtl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -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"
//
Expand Down
57 changes: 30 additions & 27 deletions src/SeerUtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,38 @@
#include "QStringPair.h"
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QMap>

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

unsigned char ebcdicToAscii (unsigned char byte);
unsigned char ucharToAscii (unsigned char byte);

int typeBytes (const QString& type);

bool readFile (const QString& filename, QStringList& lines);
}

2 changes: 2 additions & 0 deletions tests/gdbmi_condition/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
gdbmi_condition
core*
10 changes: 10 additions & 0 deletions tests/gdbmi_condition/Makefile
Original file line number Diff line number Diff line change
@@ -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 changes: 20 additions & 0 deletions tests/gdbmi_condition/gdbmi_condition.cpp
Original file line number Diff line number Diff line change
@@ -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;
}

4 changes: 2 additions & 2 deletions tests/hellofibonacci/breakpoints.seer
Original file line number Diff line number Diff line change
@@ -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")
7 changes: 6 additions & 1 deletion tests/hellofibonacci/hellofibonacci.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down