Debugger: Improve parsing of SVD file

The previous implementation was done in a hurry and a bit
overcomplicated for maintenance.

Now it is simplified and a common code moved to a separate functions.

Change-Id: I86e9131e08154ec24bb7778c3a7d4c3d6b042751
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Denis Shienkov
2020-01-30 17:07:48 +03:00
parent c50e928e76
commit d5fd6a83d8

View File

@@ -52,6 +52,8 @@ constexpr char kBitRange[] = "bitRange";
constexpr char kBitWidth[] = "bitWidth";
constexpr char kDerivedFrom[] = "derivedFrom";
constexpr char kDescription[] = "description";
constexpr char kDevice[] = "device";
constexpr char kDisplayName[] = "displayName";
constexpr char kField[] = "field";
constexpr char kFields[] = "fields";
constexpr char kGroupName[] = "groupName";
@@ -559,114 +561,24 @@ PeripheralRegisterHandler::PeripheralRegisterHandler(DebuggerEngine *engine)
setHeader({tr("Name"), tr("Value"), tr("Access")});
}
static PeripheralRegisterGroups availablePeripheralRegisterGroups(
const QString &filePath)
static void handleField(QXmlStreamReader &in, PeripheralRegister &reg)
{
QFile f(filePath);
if (!f.open(QIODevice::ReadOnly))
return {};
QXmlStreamReader in(&f);
PeripheralRegisterGroups foundGroups;
while (!in.atEnd()) {
const auto token = in.readNext();
if (token == QXmlStreamReader::EndElement
&& in.name() == QLatin1String(kPeripherals)) {
break;
} else if (token != QXmlStreamReader::StartElement
|| in.name() != QLatin1String(kPeripheral)) {
continue;
}
PeripheralRegisterGroup group;
const auto fromGroupName = in.attributes().value(
QLatin1String(kDerivedFrom));
const auto foundGroupEnd = foundGroups.cend();
const auto foundGroupIt = std::find_if(
foundGroups.cbegin(), foundGroupEnd,
[fromGroupName](const PeripheralRegisterGroup &foundGroup) {
return fromGroupName == foundGroup.name;
});
if (foundGroupIt != foundGroupEnd)
group = *foundGroupIt;
while (!in.atEnd()) {
const auto token = in.readNext();
if (token == QXmlStreamReader::EndElement
&& in.name() == QLatin1String(kPeripheral)) {
foundGroups.push_back(group);
break;
} else if (token == QXmlStreamReader::StartElement) {
const auto elementName = in.name();
if (elementName == QLatin1String(kName)) {
group.name = in.readElementText();
} else if (elementName == QLatin1String(kDescription)) {
group.description = in.readElementText();
} else if (elementName == QLatin1String(kGroupName)) {
group.displayName = in.readElementText();
} else if (elementName == QLatin1String(kBaseAddress)) {
group.baseAddress = decodeNumeric(in.readElementText());
} else if (elementName == QLatin1String(kSize)) {
group.size = int(decodeNumeric(in.readElementText()));
} else if (elementName == QLatin1String(kAccess)) {
group.access = decodeAccess(in.readElementText());
} else if (elementName == QLatin1String(kRegisters)
|| elementName == QLatin1String(kRegister)) {
PeripheralRegister reg;
while (!in.atEnd()) {
const auto token = in.readNext();
if (token == QXmlStreamReader::EndElement
&& in.name() == QLatin1String(kRegister)) {
group.registers.push_back(reg);
break;
} else if (token == QXmlStreamReader::StartElement) {
const auto elementName = in.name();
if (elementName == QLatin1String(kRegister)) {
continue;
} else if (elementName == QLatin1String(kName)) {
reg.name = in.readElementText();
} else if (elementName == QLatin1String(kDescription)) {
reg.description = in.readElementText();
} else if (elementName == QLatin1String(kAddressOffset)) {
reg.addressOffset = decodeNumeric(in.readElementText());
} else if (elementName == QLatin1String(kSize)) {
reg.size = int(decodeNumeric(in.readElementText()));
} else if (elementName == QLatin1String(kAccess)) {
reg.access = decodeAccess(in.readElementText());
} else if (elementName == QLatin1String(kResetvalue)) {
reg.resetValue = decodeNumeric(in.readElementText());
} else if (elementName == QLatin1String(kFields)
|| elementName == QLatin1String(kField)) {
PeripheralRegisterField fld;
while (!in.atEnd()) {
const auto token = in.readNext();
if (token == QXmlStreamReader::EndElement
&& in.name() == QLatin1String(kField)) {
reg.fields.push_back(fld);
break;
} else if (token == QXmlStreamReader::StartElement) {
while (in.readNextStartElement()) {
const auto elementName = in.name();
if (elementName == QLatin1String(kField)) {
continue;
} else if (elementName == QLatin1String(kName)) {
if (elementName == kName) {
fld.name = in.readElementText();
} else if (elementName == QLatin1String(kDescription)) {
} else if (elementName == kDescription) {
fld.description = in.readElementText();
} else if (elementName == QLatin1String(kAccess)) {
} else if (elementName == kAccess) {
fld.access = decodeAccess(in.readElementText());
} else if (elementName == QLatin1String(kBitRange)) {
} else if (elementName == kBitRange) {
const QString elementText = in.readElementText();
const int startBracket = elementText.indexOf('[');
const int endBracket = elementText.indexOf(']');
if (startBracket == -1 || endBracket == -1
|| (endBracket - startBracket) <= 0) {
if (startBracket == -1 || endBracket == -1 || (endBracket - startBracket) <= 0)
continue;
}
const QString range = elementText.mid(
startBracket + 1, endBracket - 1);
const QString range = elementText.mid(startBracket + 1, endBracket - 1);
const QStringList items = range.split(':');
enum { MaxBit, MinBit, BitsCount };
if (items.count() != BitsCount)
@@ -675,28 +587,123 @@ static PeripheralRegisterGroups availablePeripheralRegisterGroups(
const int to = int(decodeNumeric(items.at(MaxBit)));
fld.bitOffset = from;
fld.bitWidth = to - from + 1;
} else if (elementName == QLatin1String(kBitOffset)) {
} else if (elementName == kBitOffset) {
fld.bitOffset = int(decodeNumeric(in.readElementText()));
} else if (elementName == QLatin1String(kBitWidth)) {
} else if (elementName == kBitWidth) {
fld.bitWidth = int(decodeNumeric(in.readElementText()));
} else {
in.skipCurrentElement();
}
}
}
} else {
in.skipCurrentElement();
}
}
}
} else {
in.skipCurrentElement();
}
}
}
reg.fields.push_back(fld);
}
return foundGroups;
static void handleRegister(QXmlStreamReader &in, PeripheralRegisterGroup &group)
{
PeripheralRegister reg;
while (in.readNextStartElement()) {
const auto elementName = in.name();
if (elementName == kName) {
reg.name = in.readElementText();
} else if (elementName == kDisplayName) {
reg.displayName = in.readElementText();
} else if (elementName == kDescription) {
reg.description = in.readElementText();
} else if (elementName == kAddressOffset) {
reg.addressOffset = decodeNumeric(in.readElementText());
} else if (elementName == kSize) {
reg.size = int(decodeNumeric(in.readElementText()));
} else if (elementName == kAccess) {
reg.access = decodeAccess(in.readElementText());
} else if (elementName == kResetvalue) {
reg.resetValue = decodeNumeric(in.readElementText());
} else if (elementName == kFields) {
while (in.readNextStartElement()) {
const auto elementName = in.name();
if (elementName == kField)
handleField(in, reg);
else
in.skipCurrentElement();
}
} else {
in.skipCurrentElement();
}
}
group.registers.push_back(reg);
}
static void handleGroup(QXmlStreamReader &in, PeripheralRegisterGroups &groups)
{
PeripheralRegisterGroup group;
const auto fromGroupName = in.attributes().value(kDerivedFrom);
if (!fromGroupName.isEmpty()) {
const auto groupEnd = groups.cend();
const auto groupIt = std::find_if(groups.cbegin(), groupEnd,
[fromGroupName](const PeripheralRegisterGroup &group) {
return fromGroupName == group.name;
});
if (groupIt != groupEnd)
group = *groupIt;
}
while (in.readNextStartElement()) {
const auto elementName = in.name();
if (elementName == kName) {
group.name = in.readElementText();
} else if (elementName == kDescription) {
group.description = in.readElementText();
} else if (elementName == kGroupName) {
group.displayName = in.readElementText();
} else if (elementName == kBaseAddress) {
group.baseAddress = decodeNumeric(in.readElementText());
} else if (elementName == kSize) {
group.size = int(decodeNumeric(in.readElementText()));
} else if (elementName == kAccess) {
group.access = decodeAccess(in.readElementText());
} else if (elementName == kRegisters) {
while (in.readNextStartElement()) {
const auto elementName = in.name();
if (elementName == kRegister)
handleRegister(in, group);
else
in.skipCurrentElement();
}
} else {
in.skipCurrentElement();
}
}
groups.push_back(group);
}
static PeripheralRegisterGroups availablePeripheralRegisterGroups(const QString &filePath)
{
QFile f(filePath);
if (!f.open(QIODevice::ReadOnly))
return {};
QXmlStreamReader in(&f);
PeripheralRegisterGroups groups;
while (in.readNextStartElement()) {
const auto elementName = in.name();
if (elementName == kDevice) {
while (in.readNextStartElement()) {
const auto elementName = in.name();
if (elementName == kPeripherals) {
while (in.readNextStartElement()) {
const auto elementName = in.name();
if (elementName == kPeripheral)
handleGroup(in, groups);
else
in.skipCurrentElement();
}
} else {
in.skipCurrentElement();
}
}
}
}
return groups;
}
void PeripheralRegisterHandler::updateRegisterGroups()