1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
|
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2023 Christian Hohnstaedt.
*
* All rights reserved.
*/
#include <QStringList>
#include <QDebug>
#include <QElapsedTimer>
#include <QFileInfo>
#include <QDir>
#include <stdlib.h>
#include "debug_info.h"
#include "base.h"
#include "func.h"
QList<dbg_pattern> debug_info::patternlist;
bool debug_info::all = false;
dbg_pattern::dbg_pattern(QString part)
: first(0), last(INT_MAX), inv(false)
{
bool ok;
if (part[0] == '-') {
inv = true;
part.remove(0, 1);
}
file = func = part;
QStringList file_num = part.split(":");
if (file_num.size() == 2) {
file = file_num[0];
file_num = file_num[1].split("-");
if (file_num.size() == 1) {
first = last = file_num[0].toUInt();
} else {
if (!file_num[0].isEmpty()) {
first = file_num[0].toUInt(&ok);
Q_ASSERT(ok);
}
if (!file_num[1].isEmpty()) {
last = file_num[1].toUInt(&ok);
Q_ASSERT(ok);
}
}
}
file = QDir::cleanPath(file);
qDebug() << "New debug match" << (inv ? "Not" : "") << file << func << first << last;
}
bool dbg_pattern::match(const QString &curr_file, const QString &curr_func,
unsigned line) const
{
// QTextStream out(stdout);
// out << QString("MATCH %1:%2(%3)\n").arg(curr_file).arg(curr_func).arg(line);
if (curr_func == func)
return true;
if (curr_func.endsWith(QString("::%1").arg(func)))
return true;
if (curr_file != file && !file.endsWith(QString("/%1").arg(curr_file)))
return false;
if (line >= first && line <= last)
return true;
return false;
}
void debug_info::set_debug(const QString &dbg)
{
bool local_all = false;
all = true;
if (isEmpty()) {
foreach(QString part, dbg.split(",")) {
if (part.toLower() == "all") {
local_all = true;
continue;
}
dbg_pattern d(part);
patternlist.insert(d.invert() ? 0 : patternlist.size(), d);
}
}
all = local_all;
}
debug_info::debug_info(const QMessageLogContext &ctx)
: line(0)
{
line = ctx.line;
if (ctx.file && ctx.line) {
QFileInfo f(ctx.file);
short_file = f.fileName();
short_func = ctx.function;
int pos = short_func.indexOf("(");
short_func.remove(pos, short_func.size());
pos = short_func.lastIndexOf(" ");
short_func.remove(0, pos +1);
}
//std::cerr << "DBG '" << (ctx.function ?: "(NULL)" )<< "' '" << CCHAR(short_func) << "' " << short_file << std::endl;
}
QString debug_info::log_prefix() const
{
if (short_file == nullptr && line == 0)
return QString();
return QString(" " COL_MAGENTA "%1" COL_GREEN COL_BOLD ":%2 " COL_BLUE "%3")
.arg(short_file).arg(line).arg(short_func);
}
bool debug_info::do_debug() const
{
foreach(dbg_pattern pattern, patternlist) {
if (pattern.match(short_file, short_func, line))
return !pattern.invert();
}
return all;
}
static void myMessageOutput(QtMsgType type, const QMessageLogContext &ctx,
const QString &msg)
{
static QElapsedTimer *t;
static int abort_on_warning = -1;
const char *severity = "Unknown", *warn_msg = NULL;
int el;
if (!t) {
t = new QElapsedTimer();
t->start();
}
if (abort_on_warning == -1) {
char *a = getenv("XCA_ABORT_ON_WARNING");
abort_on_warning = a && *a;
}
debug_info dinfo(ctx);
el = t->elapsed();
switch (type) {
case QtDebugMsg:
if (!dinfo.do_debug())
return;
severity = COL_CYAN "Debug";
break;
case QtWarningMsg: warn_msg = "WARNING"; severity = COL_LRED "Warning"; break;
case QtCriticalMsg: warn_msg = "CRITICAL"; severity = COL_RED "Critical"; break;
case QtFatalMsg: warn_msg = "FATAL"; severity = COL_RED "Fatal"; break;
case QtInfoMsg: severity = COL_CYAN "Info"; break;
default: severity = COL_CYAN "Default"; break;
}
console_write(stderr, QString(COL_YELL "%1%2 %3:%5" COL_RESET " %4\n")
.arg(el/1000, 4)
.arg((el%1000)/100, 2, 10, QChar('0'))
.arg(severity).arg(msg)
.arg(dinfo.log_prefix()).toUtf8());
if (abort_on_warning == 1 && warn_msg) {
qFatal("Abort on %s", warn_msg);
}
}
void debug_info::init()
{
qInstallMessageHandler(myMessageOutput);
const char *d = getenv("XCA_DEBUG");
if (d && *d)
debug_info::set_debug(QString(d));
}
|