BareMetal: Handle details preceding it message in the KEIL parser

We need to handle a multi-line error messages from the KEIL A51
assembler:

 http://www.keil.com/support/man/docs/a51/a51_er_nonfatalerror.htm

This assembler produces an error messages in the form like:

 00B0                 114         ljmp    usb_stub_isr     ; (B0) GPIF operation complete.
 *** _____________________________________^
 *** ERROR #A45 IN 114 (autovec_keil.a51, LINE 114): UNDEFINED SYMBOL
 00B4                 116         ljmp    usb_stub_isr     ; (B4) GPIF waveform.
 *** _____________________________________^
 *** ERROR #A45 IN 116 (autovec_keil.a51, LINE 116): UNDEFINED SYMBOL

where the details places before than a main message text.

This patch handles this error messages, but with an one limitation in that a details
should start with a four hexadecimal letters (in a common case it can not
contains that letters at all).

Change-Id: I0c9bf7ab72e1aef32498af5a1ef29c9221c185d5
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
Denis Shienkov
2019-10-15 13:31:46 +03:00
parent 36a422e7be
commit f723531f8f
2 changed files with 76 additions and 17 deletions

View File

@@ -70,11 +70,14 @@ void KeilParser::newTask(const Task &task)
m_lines = 1;
}
void KeilParser::amendDescription(const QString &desc)
void KeilParser::amendDescription()
{
while (!m_snippets.isEmpty()) {
const QString snippet = m_snippets.takeFirst();
const int start = m_lastTask.description.count() + 1;
m_lastTask.description.append(QLatin1Char('\n'));
m_lastTask.description.append(desc);
m_lastTask.description.append('\n');
m_lastTask.description.append(snippet);
QTextLayout::FormatRange fr;
fr.start = start;
@@ -84,6 +87,7 @@ void KeilParser::amendDescription(const QString &desc)
m_lastTask.formats.append(fr);
++m_lines;
}
}
// ARM compiler specific parsers.
@@ -205,18 +209,34 @@ void KeilParser::stdError(const QString &line)
return;
if (lne.startsWith(QLatin1Char(' '))) {
amendDescription(lne);
m_snippets.push_back(lne);
return;
}
doFlush();
}
static bool hasDetailsEntry(const QString &trimmedLine)
{
const QRegularExpression re("^([0-9A-F]{4})");
const QRegularExpressionMatch match = re.match(trimmedLine);
return match.hasMatch();
}
static bool hasDetailsPointer(const QString &trimmedLine)
{
if (!trimmedLine.startsWith("*** "))
return false;
if (!trimmedLine.endsWith('^'))
return false;
return trimmedLine.contains('_');
}
void KeilParser::stdOutput(const QString &line)
{
IOutputParser::stdOutput(line);
const QString lne = rightTrimmed(line);
QString lne = rightTrimmed(line);
// Check for MSC51 compiler specific patterns.
const bool parsed = parseMcs51WarningOrErrorDetailsMessage1(lne)
@@ -228,10 +248,28 @@ void KeilParser::stdOutput(const QString &line)
return;
}
if (lne.startsWith(QLatin1Char(' '))) {
amendDescription(lne);
if (m_lastTask.isNull()) {
// Check for details, which are comes on a previous
// lines, before the message.
// This code handles the details in a form like:
// 0000 24 ljmp usb_stub_isr ; (00) Setup data available.
// *** _____________________________________^
// 003C 54 ljmp usb_stub_isr ; (3C) EP8 in/out.
// *** _____________________________________^
if (hasDetailsEntry(lne) || hasDetailsPointer(lne)) {
lne.replace(0, 4, " ");
m_snippets.push_back(lne);
return;
}
} else {
// Check for details, which are comes on a next
// lines, after the message.
if (lne.startsWith(' ')) {
m_snippets.push_back(lne);
return;
}
}
doFlush();
}
@@ -241,6 +279,8 @@ void KeilParser::doFlush()
if (m_lastTask.isNull())
return;
amendDescription();
Task t = m_lastTask;
m_lastTask.clear();
emit addTask(t, m_lines, 1);
@@ -425,6 +465,24 @@ void BareMetalPlugin::testKeilOutputParsers_data()
categoryCompile))
<< QString();
QTest::newRow("MCS51: Assembler details error")
<< QString::fromLatin1("01AF Some detail\n"
"*** ___^\n"
"*** ERROR #A45 IN 28 (d:\\foo.a51, LINE 28): Some error")
<< OutputParserTester::STDOUT
<< QString::fromLatin1("01AF Some detail\n"
"*** ___^\n"
"*** ERROR #A45 IN 28 (d:\\foo.a51, LINE 28): Some error\n")
<< QString()
<< (Tasks() << Task(Task::Error,
QLatin1String("#A45: Some error\n"
" Some detail\n"
" ___^"),
Utils::FilePath::fromUserInput(QLatin1String("d:\\foo.a51")),
28,
categoryCompile))
<< QString();
// Compiler messages.
QTest::newRow("MCS51: Compiler simple warning")
<< QString::fromLatin1("*** WARNING C123 IN LINE 13 OF c:\\foo.c: Some warning")

View File

@@ -43,7 +43,7 @@ public:
private:
void newTask(const ProjectExplorer::Task &task);
void amendDescription(const QString &desc);
void amendDescription();
// ARM compiler specific parsers.
bool parseArmWarningOrErrorDetailsMessage(const QString &lne);
@@ -61,6 +61,7 @@ private:
ProjectExplorer::Task m_lastTask;
int m_lines = 0;
QStringList m_snippets;
};
} // namespace Internal