21 #define KDE_EXTENDED_DEBUG_OUTPUT
23 #ifndef QT_NO_CAST_FROM_ASCII
24 #define QT_NO_CAST_FROM_ASCII
26 #ifndef QT_NO_CAST_TO_ASCII
27 #define QT_NO_CAST_TO_ASCII
34 #include <QThreadStorage>
54 #ifdef HAVE_SYS_TIME_H
71 #include <QtCore/QFile>
72 #include <QtCore/QHash>
73 #include <QtCore/QObject>
74 #include <QtCore/QChar>
75 #include <QtCore/QCoreApplication>
93 #define HAVE_BACKTRACE (1)
99 #define HAVE_BACKTRACE_DEMANGLE
115 KNoDebugStream() {
open(WriteOnly); }
122 class KSyslogDebugStream:
public KNoDebugStream
131 syslog(m_priority,
"%s", buf.constData());
135 void setPriority(
int priority) { m_priority = priority; }
140 class KFileDebugStream:
public KNoDebugStream
147 QFile aOutputFile(m_fileName);
148 if (aOutputFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Unbuffered)) {
150 aOutputFile.write(buf.
trimmed());
151 aOutputFile.putChar(
'\n');
156 void setFileName(
const QString& fn) { m_fileName = fn; }
161 class KMessageBoxDebugStream:
public KNoDebugStream
174 void setCaption(
const QString& h) { m_caption = h; }
179 class KLineEndStrippingDebugStream:
public KNoDebugStream
195 MessageBoxOutput = 1,
199 DefaultOutput = QtOutput,
204 inline Area() { clear(); }
205 void clear(OutputMode set =
Unknown)
207 for (
int i = 0; i < 4; ++i) {
208 logFileName[i].clear();
220 :
config(0), kDebugDBusIface(0), m_disableAll(false), m_seenMainComponent(false)
222 Q_ASSERT(
int(QtDebugMsg) == 0);
223 Q_ASSERT(
int(QtFatalMsg) == 3);
241 for (
int i = 0; i < 8; i++) {
242 m_nullOutputYesNoCache[i] = -1;
250 delete kDebugDBusIface;
258 Area &areaData = cache[0];
263 m_seenMainComponent =
true;
265 areaData.name = qApp ? qAppName().toUtf8() :
QByteArray(
"unnamed app");
266 m_seenMainComponent =
false;
270 for (
int i = 0; i < 8; i++) {
271 m_nullOutputYesNoCache[i] = -1;
275 if (filename.isEmpty()) {
278 QFile file(filename);
279 if (!file.open(QIODevice::ReadOnly)) {
280 qWarning(
"Couldn't open %s", filename.toLocal8Bit().constData());
287 while (!file.atEnd()) {
294 unsigned char ch=line[i];
299 if (ch < '0' || ch >
'9') {
300 qWarning(
"Syntax error parsing '%s': no number (line %u)", qPrintable(filename), lineNumber);
306 }
while (ch >=
'0' && ch <=
'9' && i < line.
length());
310 while (i < line.
length() && line[i] <=
' ')
314 areaData.name = line.
mid(i);
315 cache.
insert(number, areaData);
320 inline int level(QtMsgType type)
321 {
return int(type) - int(QtDebugMsg); }
323 QString groupNameForArea(
unsigned int area)
const
332 OutputMode areaOutputMode(QtMsgType type,
unsigned int area,
bool enableByDefault)
358 const int mode = cg.readEntry(key,
int(enableByDefault ? DefaultOutput : NoOutput));
359 return OutputMode(mode);
362 QString logFileName(QtMsgType type,
unsigned int area)
371 aKey =
"InfoFilename";
374 aKey =
"WarnFilename";
377 aKey =
"FatalFilename";
381 aKey =
"ErrorFilename";
398 Cache::Iterator areaData(QtMsgType type,
unsigned int num,
bool enableByDefault =
true)
400 if (!cache.contains(0)) {
403 Q_ASSERT(cache.contains(0));
407 m_seenMainComponent =
true;
411 if (it == cache.end()) {
413 Q_ASSERT(cache.contains(0));
419 static bool s_firstDebugFromApplication =
true;
420 if (s_firstDebugFromApplication && !m_disableAll) {
421 s_firstDebugFromApplication =
false;
423 writeGroupForNamedArea(it->name, enableByDefault);
427 const int lev = level(type);
430 it->mode[lev] = areaOutputMode(type, num, enableByDefault);
431 if (it->mode[lev] == FileOutput && it->logFileName[lev].isEmpty())
432 it->logFileName[lev] = logFileName(type, num);
434 Q_ASSERT(it->mode[lev] !=
Unknown);
441 if (!filewriter.hasLocalData())
442 filewriter.setLocalData(
new KFileDebugStream);
443 filewriter.localData()->setFileName(fileName);
444 QDebug result(filewriter.localData());
450 if (!messageboxwriter.hasLocalData())
451 messageboxwriter.setLocalData(
new KMessageBoxDebugStream);
452 QDebug result(messageboxwriter.localData());
460 header =
"Warning (";
463 header =
"Fatal Error (";
477 QDebug setupSyslogWriter(QtMsgType type)
479 if (!syslogwriter.hasLocalData())
480 syslogwriter.setLocalData(
new KSyslogDebugStream);
481 QDebug result(syslogwriter.localData());
499 syslogwriter.localData()->setPriority(level);
503 QDebug setupQtWriter(QtMsgType type)
505 if (type != QtDebugMsg) {
506 if (type == QtWarningMsg) {
514 return QDebug(&lineendstrippingwriter);
517 QDebug printHeader(
QDebug s,
const QByteArray &areaName,
const char * file,
int line,
const char *funcinfo, QtMsgType type,
bool colored)
519 #ifdef KDE_EXTENDED_DEBUG_OUTPUT
520 static bool printProcessInfo = (qgetenv(
"KDE_DEBUG_NOPROCESSINFO").isEmpty());
521 static bool printAreaName = (qgetenv(
"KDE_DEBUG_NOAREANAME").isEmpty());
522 static bool printMethodName = (qgetenv(
"KDE_DEBUG_NOMETHODNAME").isEmpty());
523 static bool printFileLine = (!qgetenv(
"KDE_DEBUG_FILELINE").isEmpty());
525 static int printTimeStamp = qgetenv(
"KDE_DEBUG_TIMESTAMP").toInt();
528 if (printTimeStamp > 0) {
529 if (printTimeStamp >= 2) {
540 if (printProcessInfo) {
541 programName = cache.value(0).name;
546 programName =
"<unknown program name>";
548 s << programName.
constData() <<
"(" << unsigned(getpid()) <<
")";
550 if (printAreaName && (!printProcessInfo || areaName != programName)) {
551 if (printProcessInfo)
556 if (m_indentString.hasLocalData()) {
557 s << m_indentString.localData()->toLatin1().constData();
561 s <<
' ' << file <<
':' << line <<
' ';
564 if (funcinfo && printMethodName) {
566 if (type <= QtDebugMsg)
577 Q_ASSERT_X(pos != -1,
"kDebug",
578 "Bug in kDebug(): I don't know how to parse this function name");
579 while (info.
at(pos - 1) ==
' ')
581 pos = info.
indexOf(
'(', pos + 1);
588 index = info.
indexOf(
"<unnamed>::", index);
592 if ( info.
at(index-1) !=
':' )
595 index += strlen(
"<unnamed>::");
600 if (startoftemplate != -1 && pos > startoftemplate &&
606 if (pos + 1 == info.
length())
608 s <<
" " << funcinfo;
612 s <<
" " << funcinfo;
627 QDebug stream(QtMsgType type,
unsigned int area,
const char *debugFile,
int line,
628 const char *funcinfo)
630 static bool env_colored = (!qgetenv(
"KDE_COLOR_DEBUG").isEmpty());
631 static bool env_colors_on_any_fd = (!qgetenv(
"KDE_COLOR_DEBUG_ALWAYS").isEmpty());
633 OutputMode mode = it->mode[level(type)];
635 QString file = it->logFileName[level(type)];
639 areaName = cache.value(0).name;
646 s = setupFileWriter(file);
648 case MessageBoxOutput:
649 s = setupMessageBoxWriter(type, areaName);
652 s = setupSyslogWriter(type);
660 s = setupQtWriter(type);
663 colored = env_colored && (env_colors_on_any_fd || isatty(fileno(stderr)));
668 return printHeader(s, areaName, debugFile, line, funcinfo, type, colored);
671 void writeGroupForNamedArea(
const QByteArray& areaName,
bool enabled)
675 KConfig* cfgObj = configObject();
679 if (!cg.hasKey(key)) {
680 cg.writeEntry(key,
int(enabled ? KDebugPrivate::QtOutput : KDebugPrivate::NoOutput));
691 bool m_seenMainComponent;
692 int m_nullOutputYesNoCache[8];
694 KNoDebugStream devnull;
699 KLineEndStrippingDebugStream lineendstrippingwriter;
704 #ifdef HAVE_BACKTRACE
707 #ifdef HAVE_BACKTRACE_DEMANGLE
708 const int len = strlen(name);
710 const int mangledNameStart = in.
indexOf(
"(_");
711 if (mangledNameStart >= 0) {
712 const int mangledNameEnd = in.
indexOf(
'+', mangledNameStart + 2);
713 if (mangledNameEnd >= 0) {
717 name[mangledNameEnd] = 0;
718 char *demangled = abi::__cxa_demangle(name + mangledNameStart + 1, 0, 0, &status);
719 name[mangledNameEnd] =
'+';
737 #ifdef HAVE_BACKTRACE
739 int n = backtrace(trace, 256);
742 char** strings = backtrace_symbols (trace, n);
745 n = qMin( n, levels );
748 for (
int i = 0; i < n; ++i)
760 return QDebug(&kDebug_data->devnull);
765 if (kDebug_data.isDestroyed()) {
767 qCritical().
nospace() <<
"kDebugStream called after destruction (from "
768 << (funcinfo ? funcinfo :
"")
769 << (file ?
" file " :
" unknown file")
771 <<
" line " << line <<
")";
776 return kDebug_data->stream(level, area, file, line, funcinfo);
801 if (!kDebug_data)
return;
802 KDebugPrivate* d = kDebug_data;
808 end = d->cache.end();
809 for ( ; it != end; ++it)
812 for (
int i = 0; i < 8; i++) {
813 d->m_nullOutputYesNoCache[i] = -1;
821 bool enableByDefault)
826 if (kDebug_data.isDestroyed()) {
830 KDebugPrivate *
const d = kDebug_data;
833 if (type == QtDebugMsg) {
834 int *entries = d->m_nullOutputYesNoCache;
835 for (
int i = 0; i < 8; i += 2) {
836 if (entries[i] == area) {
837 return entries[i + 1];
843 const bool ret = it->mode[d->level(type)] == KDebugPrivate::NoOutput;
846 if (type == QtDebugMsg) {
847 int *entries = d->m_nullOutputYesNoCache;
848 int idx = (qrand() % 4) * 2;
850 entries[idx + 1] = ret;
859 KDebugPrivate* d = kDebug_data;
862 while (d->cache.contains(areaNumber)) {
865 KDebugPrivate::Area areaData;
866 areaData.name = areaName;
868 d->cache.insert(areaNumber, areaData);
869 d->writeGroupForNamedArea(areaName, enabled);
873 #ifndef KDE_NO_DEBUG_OUTPUT
875 class KDebug::Block::Private
882 : m_label(0), m_area(area), d(0)
890 kDebug(area) <<
"BEGIN:" << label;
904 const double duration = m_startTime.elapsed() / 1000.0;
909 if (duration < 5.0) {
912 << d->m_label.constData()
917 << d->m_label.constData()
void message(KMessage::MessageType messageType, const QString &text, const QString &caption=QString())
Display a long message of a certain type.
bool kde_kdebug_enable_dbus_interface
uint toUInt(bool *ok, int base) const
QDebug perror(QDebug s, KDebugTag)
Date/times with associated time zone.
QByteArray trimmed() const
static bool hasNullOutput(QtMsgType type, bool condition, int area, bool enableByDefault)
int lastIndexOf(char ch, int from) const
#define K_GLOBAL_STATIC(TYPE, NAME)
This macro makes it easy to use non-POD types as global statics.
static QString locate(const char *type, const QString &filename, const KComponentData &cData=KGlobal::mainComponent())
This function is just for convenience.
Same format as Qt::TextDate (i.e.
bool hasGroup(const QString &group) const
Returns true if the specified group is known about.
KConfigGroup group(const QByteArray &group)
Returns an object for the named subgroup.
QString toString(const QString &format) const
Returns the date/time as a string.
QByteArray fromRawData(const char *data, int size)
QByteArray & insert(int i, char ch)
bool isDateOnly() const
Returns whether the instance represents a date/time or a date-only value.
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
virtual qint64 readData(char *data, qint64 maxSize)=0
virtual bool isSequential() const
Represents and parses a URL.
KSharedConfigPtr config()
Returns the general config object.
void setLocalData(T data)
int indexOf(char ch, int from) const
QString number(int n, int base)
QString fromLocal8Bit(const char *str, int size)
bool hasLocalData() const
QString fromUtf8(const char *str, int size)
Cascade to system settings, but omit user's globals.
QDebug operator<<(QDebug s, const KDateTime &time)
const char * constData() const
static int registerArea(const QByteArray &areaName, bool enabled=true)
QCoreApplication * instance()
QString componentName() const
Returns the name of the component.
QByteArray mid(int pos, int len) const
static bool hasNullOutputQtDebugMsg(int area=KDE_DEFAULT_DEBUG_AREA)
static QString maybeDemangledName(char *name)
A class representing a date and time with an associated time zone.
A class for one specific group in a KConfig object.
virtual qint64 readLineData(char *data, qint64 maxSize)
The central class of the KDE configuration data system.
QByteArray left(int len) const
QDateTime currentDateTime()
char * toString(const T &value)
virtual qint64 writeData(const char *data, qint64 maxSize)=0
const KComponentData & mainComponent()
Returns the global component data.
QDebug kDebugStream(QtMsgType level, int area, const char *file, int line, const char *funcinfo)
Block(const char *label, int area=KDE_DEFAULT_DEBUG_AREA)
QString fromLatin1(const char *str, int size)
D-Bus interface to KDebug.
T readEntry(const QString &key, const T &aDefault) const
Reads the value of an entry specified by pKey in the current group.
QString prettyUrl(AdjustPathOption trailing=LeaveTrailingSlash) const
Returns the URL as string in human-friendly format.
QString kRealBacktrace(int levels)
QByteArray toUtf8() const