/* Copyright (C) 2010 Milian Wolff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "gdbhighlighter.h" #include #include GdbHighlighter::GdbHighlighter(QTextDocument* parent, const QList & gdbLines) : QSyntaxHighlighter(parent) { // setup line lookup int l = 0; foreach(const BacktraceLine& line, gdbLines) { lines.insert(l, line); l += line.toString().count('\n'); } // Add a dummy, in case the last backtrace line has more than 1 '\n' char. const BacktraceLine dummy; lines.insert(l, dummy); // setup formates KColorScheme scheme(QPalette::Active); crashFormat.setForeground(scheme.foreground(KColorScheme::NegativeText)); nullptrFormat.setForeground(scheme.foreground(KColorScheme::NegativeText)); nullptrFormat.setFontWeight(QFont::Bold); assertFormat = nullptrFormat; threadFormat.setForeground(scheme.foreground(KColorScheme::NeutralText)); urlFormat.setForeground(scheme.foreground(KColorScheme::LinkText)); funcFormat.setForeground(scheme.foreground(KColorScheme::VisitedText)); funcFormat.setFontWeight(QFont::Bold); otheridFormat.setForeground(scheme.foreground(KColorScheme::PositiveText)); crapFormat.setForeground(scheme.foreground(KColorScheme::InactiveText)); } void GdbHighlighter::highlightBlock(const QString& text) { int cur = 0; int next; int diff; const QRegExp hexptrPattern("0x[0-9a-f]+", Qt::CaseSensitive, QRegExp::RegExp2); int lineNr = currentBlock().firstLineNumber(); while ( cur < text.length() ) { next = text.indexOf('\n', cur); if (next == -1) { next = text.length(); } if (lineNr == 0) { // line that contains 'Application: ...' ++lineNr; cur = next; continue; } diff = next - cur; QString lineStr = text.mid(cur, diff).append('\n'); // -1 since we skip the first line QMap< int, BacktraceLine >::iterator it = lines.lowerBound(lineNr - 1); Q_ASSERT(it != lines.end()); // QMap::lowerBound() returns the next higher item or // the dummy item, but we want the one before that. if (it.key() > lineNr - 1) { --it; } const BacktraceLine& line = it.value(); if (line.type() == BacktraceLine::KCrash) { setFormat(cur, diff, crashFormat); } else if (line.type() == BacktraceLine::ThreadStart || line.type() == BacktraceLine::ThreadIndicator) { setFormat(cur, diff, threadFormat); } else if (line.type() == BacktraceLine::Crap) { setFormat(cur, diff, crapFormat); } else if (line.type() == BacktraceLine::StackFrame) { if (!line.fileName().isEmpty()) { int colonPos = line.fileName().lastIndexOf(':'); setFormat(lineStr.indexOf(line.fileName()), colonPos == -1 ? line.fileName().length() : colonPos, urlFormat); } if (!line.libraryName().isEmpty()) { setFormat(lineStr.indexOf(line.libraryName()), line.libraryName().length(), urlFormat); } if (!line.functionName().isEmpty()) { int idx = lineStr.indexOf(line.functionName()); if (idx != -1) { // highlight Id::Id::Id::Func // Id should have otheridFormat, :: no format and Func funcFormat int i = idx; int from = idx; while (i < idx + line.functionName().length()) { if (lineStr.at(i) == ':') { setFormat(from, i - from, otheridFormat); // skip :: i += 2; from = i; continue; } else if (lineStr.at(i) == '<' || lineStr.at(i) == '>') { setFormat(from, i - from, otheridFormat); ++i; from = i; continue; } ++i; } if (line.functionName() == "qFatal" || line.functionName() == "abort" || line.functionName() == "__assert_fail" || line.functionName() == "*__GI___assert_fail" || line.functionName() == "*__GI_abort") { setFormat(from, i - from, assertFormat); } else { setFormat(from, i - from, funcFormat); } } } // highlight hexadecimal ptrs int idx = 0; while ((idx = hexptrPattern.indexIn(lineStr, idx)) != -1) { if (hexptrPattern.cap() == "0x0") { setFormat(idx, hexptrPattern.matchedLength(), nullptrFormat); } idx += hexptrPattern.matchedLength(); } } cur = next; ++lineNr; } }