• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

KDECore

  • sources
  • kde-4.14
  • kdelibs
  • kdecore
  • io
kdebug.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE libraries
2  Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
3  2002 Holger Freyther (freyther@kde.org)
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to
17  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19 */
20 
21 #define KDE_EXTENDED_DEBUG_OUTPUT
22 
23 #ifndef QT_NO_CAST_FROM_ASCII
24 #define QT_NO_CAST_FROM_ASCII
25 #endif
26 #ifndef QT_NO_CAST_TO_ASCII
27 #define QT_NO_CAST_TO_ASCII
28 #endif
29 #ifndef KDE3_SUPPORT
30 #define KDE3_SUPPORT
31 #endif
32 
33 #include "kdebug.h"
34 #include <QThreadStorage>
35 
36 #ifdef Q_WS_WIN
37 #include <fcntl.h>
38 #include <windows.h>
39 #ifndef _WIN32_WCE
40 #include <wincon.h>
41 #endif
42 #else
43 #include <unistd.h>
44 #include <stdio.h>
45 #endif
46 
47 #ifdef NDEBUG
48 #undef kDebug
49 #undef kBacktrace
50 #endif
51 
52 #include <config.h>
53 
54 #ifdef HAVE_SYS_TIME_H
55 #include <sys/time.h>
56 #endif
57 #ifdef HAVE_TIME_H
58 #include <time.h>
59 #endif
60 
61 #include "kglobal.h"
62 #include "kstandarddirs.h"
63 #include "kdatetime.h"
64 #include "kcmdlineargs.h"
65 
66 #include <kmessage.h>
67 #include <klocale.h>
68 #include <kconfiggroup.h>
69 #include <kurl.h>
70 
71 #include <QtCore/QFile>
72 #include <QtCore/QHash>
73 #include <QtCore/QObject>
74 #include <QtCore/QChar>
75 #include <QtCore/QCoreApplication>
76 
77 #include <stdlib.h> // abort
78 #include <unistd.h> // getpid
79 #include <stdarg.h> // vararg stuff
80 #include <ctype.h> // isprint
81 #include <syslog.h>
82 #include <errno.h>
83 #include <string.h>
84 #include <kconfig.h>
85 #include "kcomponentdata.h"
86 
87 #ifdef Q_OS_SOLARIS
88 // For the purposes of KDebug Solaris has a GNU-libc-compatible
89 // backtrace() function. This isn't detected by the CMake checks
90 // normally (check_function_exists fails), but we know it's there.
91 // For better results, we would use walk_context(), but that's
92 // a little more code -- see also the crash handler in kcrash.cpp .
93 #define HAVE_BACKTRACE (1)
94 #endif
95 
96 #ifdef HAVE_BACKTRACE
97 #include <execinfo.h>
98 #ifdef __GNUC__
99 #define HAVE_BACKTRACE_DEMANGLE
100 #include <cxxabi.h>
101 #endif
102 #endif
103 
104 #include "kdebugdbusiface_p.h"
105 #include <QMutex>
106 
107 
108 
109 KDECORE_EXPORT bool kde_kdebug_enable_dbus_interface = false;
110 
111 class KNoDebugStream: public QIODevice
112 {
113  // Q_OBJECT
114 public:
115  KNoDebugStream() { open(WriteOnly); }
116  bool isSequential() const { return true; }
117  qint64 readData(char *, qint64) { return 0; /* eof */ }
118  qint64 readLineData(char *, qint64) { return 0; /* eof */ }
119  qint64 writeData(const char *, qint64 len) { return len; }
120 };
121 
122 class KSyslogDebugStream: public KNoDebugStream
123 {
124  // Q_OBJECT
125 public:
126  qint64 writeData(const char *data, qint64 len)
127  {
128  if (len) {
129  // not using fromRawData because we need a terminating NUL
130  const QByteArray buf(data, len);
131  syslog(m_priority, "%s", buf.constData());
132  }
133  return len;
134  }
135  void setPriority(int priority) { m_priority = priority; }
136 private:
137  int m_priority;
138 };
139 
140 class KFileDebugStream: public KNoDebugStream
141 {
142  // Q_OBJECT
143 public:
144  qint64 writeData(const char *data, qint64 len)
145  {
146  if (len) {
147  QFile aOutputFile(m_fileName);
148  if (aOutputFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Unbuffered)) {
149  QByteArray buf = QByteArray::fromRawData(data, len);
150  aOutputFile.write(buf.trimmed());
151  aOutputFile.putChar('\n');
152  }
153  }
154  return len;
155  }
156  void setFileName(const QString& fn) { m_fileName = fn; }
157 private:
158  QString m_fileName;
159 };
160 
161 class KMessageBoxDebugStream: public KNoDebugStream
162 {
163  // Q_OBJECT
164 public:
165  qint64 writeData(const char *data, qint64 len)
166  {
167  if (len) {
168  // Since we are in kdecore here, we cannot use KMsgBox
169  QString msg = QString::fromLatin1(data, len);
170  KMessage::message(KMessage::Information, msg, m_caption);
171  }
172  return len;
173  }
174  void setCaption(const QString& h) { m_caption = h; }
175 private:
176  QString m_caption;
177 };
178 
179 class KLineEndStrippingDebugStream: public KNoDebugStream
180 {
181  // Q_OBJECT
182 public:
183  qint64 writeData(const char *data, qint64 len)
184  {
185  QByteArray buf = QByteArray::fromRawData(data, len);
186  qt_message_output(QtDebugMsg, buf.trimmed().constData());
187  return len;
188  }
189 };
190 
191 struct KDebugPrivate
192 {
193  enum OutputMode {
194  FileOutput = 0,
195  MessageBoxOutput = 1,
196  QtOutput = 2,
197  SyslogOutput = 3,
198  NoOutput = 4,
199  DefaultOutput = QtOutput, // if you change DefaultOutput, also change the defaults in kdebugdialog!
200  Unknown = 5
201  };
202 
203  struct Area {
204  inline Area() { clear(); }
205  void clear(OutputMode set = Unknown)
206  {
207  for (int i = 0; i < 4; ++i) {
208  logFileName[i].clear();
209  mode[i] = set;
210  }
211  }
212 
213  QByteArray name;
214  QString logFileName[4];
215  OutputMode mode[4];
216  };
217  typedef QHash<unsigned int, Area> Cache;
218 
219  KDebugPrivate()
220  : config(0), kDebugDBusIface(0), m_disableAll(false), m_seenMainComponent(false)
221  {
222  Q_ASSERT(int(QtDebugMsg) == 0);
223  Q_ASSERT(int(QtFatalMsg) == 3);
224 
225  // Create the D-Bus interface if it has not been created yet
226  // But only register to D-Bus if we are in a process with a D-Bus event loop,
227  // otherwise introspection will just hang.
228  // Examples of processes without a D-Bus event loop: kioslaves and the main kdeinit process.
229  //
230  // How to know that we have a real event loop? That's tricky.
231  // We could delay registration in kDebugDBusIface with a QTimer, but
232  // it would still get triggered by kioslaves that use enterLoop/exitLoop
233  // to run kio jobs synchronously.
234  //
235  // Solution: we have a bool that is set by KApplication
236  // (kioslaves should use QCoreApplication but not KApplication).
237  if (kde_kdebug_enable_dbus_interface) {
238  kDebugDBusIface = new KDebugDBusIface;
239  }
240 
241  for (int i = 0; i < 8; i++) {
242  m_nullOutputYesNoCache[i] = -1;
243  }
244 
245  }
246 
247  ~KDebugPrivate()
248  {
249  delete config;
250  delete kDebugDBusIface;
251  }
252 
253  void loadAreaNames()
254  {
255  // Don't clear the cache here, that would lose previously registered dynamic areas
256  //cache.clear();
257 
258  Area &areaData = cache[0];
259  areaData.clear();
260 
261  if (KGlobal::hasMainComponent()) {
262  areaData.name = KGlobal::mainComponent().componentName().toUtf8();
263  m_seenMainComponent = true;
264  } else {
265  areaData.name = qApp ? qAppName().toUtf8() : QByteArray("unnamed app");
266  m_seenMainComponent = false;
267  }
268  //qDebug() << "loadAreaNames: area 0 has name" << areaData.name;
269 
270  for (int i = 0; i < 8; i++) {
271  m_nullOutputYesNoCache[i] = -1;
272  }
273 
274  QString filename(KStandardDirs::locate("config", QLatin1String("kdebug.areas")));
275  if (filename.isEmpty()) {
276  return;
277  }
278  QFile file(filename);
279  if (!file.open(QIODevice::ReadOnly)) {
280  qWarning("Couldn't open %s", filename.toLocal8Bit().constData());
281  file.close();
282  return;
283  }
284 
285  uint lineNumber=0;
286 
287  while (!file.atEnd()) {
288  const QByteArray line = file.readLine().trimmed();
289  ++lineNumber;
290  if (line.isEmpty())
291  continue;
292 
293  int i=0;
294  unsigned char ch=line[i];
295 
296  if (ch =='#')
297  continue; // We have an eof, a comment or an empty line
298 
299  if (ch < '0' || ch > '9') {
300  qWarning("Syntax error parsing '%s': no number (line %u)", qPrintable(filename), lineNumber);
301  continue;
302  }
303 
304  do {
305  ch=line[++i];
306  } while (ch >= '0' && ch <= '9' && i < line.length());
307 
308  unsigned int number = line.left(i).toUInt();
309 
310  while (i < line.length() && line[i] <= ' ')
311  i++;
312 
313  Area areaData;
314  areaData.name = line.mid(i);
315  cache.insert(number, areaData);
316  }
317  file.close();
318  }
319 
320  inline int level(QtMsgType type)
321  { return int(type) - int(QtDebugMsg); }
322 
323  QString groupNameForArea(unsigned int area) const
324  {
325  QString groupName = QString::number(area);
326  if (area == 0 || !config->hasGroup(groupName)) {
327  groupName = QString::fromLocal8Bit(cache.value(area).name);
328  }
329  return groupName;
330  }
331 
332  OutputMode areaOutputMode(QtMsgType type, unsigned int area, bool enableByDefault)
333  {
334  if (!configObject())
335  return QtOutput;
336 
337  QString key;
338  switch (type) {
339  case QtDebugMsg:
340  key = QLatin1String( "InfoOutput" );
341  if (m_disableAll)
342  return NoOutput;
343  break;
344  case QtWarningMsg:
345  key = QLatin1String( "WarnOutput" );
346  break;
347  case QtFatalMsg:
348  key = QLatin1String( "FatalOutput" );
349  break;
350  case QtCriticalMsg:
351  default:
352  /* Programmer error, use "Error" as default */
353  key = QLatin1String( "ErrorOutput" );
354  break;
355  }
356 
357  const KConfigGroup cg(config, groupNameForArea(area));
358  const int mode = cg.readEntry(key, int(enableByDefault ? DefaultOutput : NoOutput));
359  return OutputMode(mode);
360  }
361 
362  QString logFileName(QtMsgType type, unsigned int area)
363  {
364  if (!configObject())
365  return QString();
366 
367  const char* aKey;
368  switch (type)
369  {
370  case QtDebugMsg:
371  aKey = "InfoFilename";
372  break;
373  case QtWarningMsg:
374  aKey = "WarnFilename";
375  break;
376  case QtFatalMsg:
377  aKey = "FatalFilename";
378  break;
379  case QtCriticalMsg:
380  default:
381  aKey = "ErrorFilename";
382  break;
383  }
384 
385  KConfigGroup cg(config, groupNameForArea(area));
386  return cg.readPathEntry(aKey, QLatin1String("kdebug.dbg"));
387  }
388 
389  KConfig* configObject()
390  {
391  if (!config) {
392  config = new KConfig(QLatin1String("kdebugrc"), KConfig::NoGlobals);
393  m_disableAll = config->group(QString()).readEntry("DisableAll", false);
394  }
395  return config;
396  }
397 
398  Cache::Iterator areaData(QtMsgType type, unsigned int num, bool enableByDefault = true)
399  {
400  if (!cache.contains(0)) {
401  //qDebug() << "cache size=" << cache.count() << "loading area names";
402  loadAreaNames(); // fills 'cache'
403  Q_ASSERT(cache.contains(0));
404  } else if (!m_seenMainComponent && KGlobal::hasMainComponent()) {
405  // Update the name for area 0 once a main component exists
406  cache[0].name = KGlobal::mainComponent().componentName().toUtf8();
407  m_seenMainComponent = true;
408  }
409 
410  Cache::Iterator it = cache.find(num);
411  if (it == cache.end()) {
412  // unknown area
413  Q_ASSERT(cache.contains(0));
414  it = cache.find(0);
415  num = 0;
416  }
417 
418  if (num == 0) { // area 0 is special, it becomes the named area "appname"
419  static bool s_firstDebugFromApplication = true;
420  if (s_firstDebugFromApplication && !m_disableAll) {
421  s_firstDebugFromApplication = false;
422  //qDebug() << "First debug output from" << it->name << "writing out with default" << enableByDefault;
423  writeGroupForNamedArea(it->name, enableByDefault);
424  }
425  }
426 
427  const int lev = level(type);
428  //qDebug() << "in cache for" << num << ":" << it->mode[lev];
429  if (it->mode[lev] == Unknown)
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);
433 
434  Q_ASSERT(it->mode[lev] != Unknown);
435 
436  return it;
437  }
438 
439  QDebug setupFileWriter(const QString &fileName)
440  {
441  if (!filewriter.hasLocalData())
442  filewriter.setLocalData(new KFileDebugStream);
443  filewriter.localData()->setFileName(fileName);
444  QDebug result(filewriter.localData());
445  return result;
446  }
447 
448  QDebug setupMessageBoxWriter(QtMsgType type, const QByteArray &areaName)
449  {
450  if (!messageboxwriter.hasLocalData())
451  messageboxwriter.setLocalData(new KMessageBoxDebugStream);
452  QDebug result(messageboxwriter.localData());
453  QByteArray header;
454 
455  switch (type) {
456  case QtDebugMsg:
457  header = "Info (";
458  break;
459  case QtWarningMsg:
460  header = "Warning (";
461  break;
462  case QtFatalMsg:
463  header = "Fatal Error (";
464  break;
465  case QtCriticalMsg:
466  default:
467  header = "Error (";
468  break;
469  }
470 
471  header += areaName;
472  header += ')';
473  messageboxwriter.localData()->setCaption(QString::fromLatin1(header));
474  return result;
475  }
476 
477  QDebug setupSyslogWriter(QtMsgType type)
478  {
479  if (!syslogwriter.hasLocalData())
480  syslogwriter.setLocalData(new KSyslogDebugStream);
481  QDebug result(syslogwriter.localData());
482  int level = 0;
483 
484  switch (type) {
485  case QtDebugMsg:
486  level = LOG_INFO;
487  break;
488  case QtWarningMsg:
489  level = LOG_WARNING;
490  break;
491  case QtFatalMsg:
492  level = LOG_CRIT;
493  break;
494  case QtCriticalMsg:
495  default:
496  level = LOG_ERR;
497  break;
498  }
499  syslogwriter.localData()->setPriority(level);
500  return result;
501  }
502 
503  QDebug setupQtWriter(QtMsgType type)
504  {
505  if (type != QtDebugMsg) {
506  if (type == QtWarningMsg) {
507  // KDE warnings are not the same thing as Qt warnings
508  // in Qt, warnings indicate bad code, which must be corrected before the release
509  // in KDE, it's just something that everyone sees (including users)
510  type = QtDebugMsg;
511  }
512  return QDebug(type);
513  }
514  return QDebug(&lineendstrippingwriter);
515  }
516 
517  QDebug printHeader(QDebug s, const QByteArray &areaName, const char * file, int line, const char *funcinfo, QtMsgType type, bool colored)
518  {
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());
524 
525  static int printTimeStamp = qgetenv("KDE_DEBUG_TIMESTAMP").toInt();
526  QByteArray programName;
527  s = s.nospace();
528  if (printTimeStamp > 0) {
529  if (printTimeStamp >= 2) {
530  // the extended print: 17:03:24.123
531  const QString sformat = QString::fromLatin1("hh:mm:ss.zzz");
532  s << qPrintable(QDateTime::currentDateTime().time().toString(sformat));
533  } else {
534  // the default print: 17:03:24
535  s << qPrintable(QDateTime::currentDateTime().time().toString());
536  }
537  s << ' ';
538  }
539 
540  if (printProcessInfo) {
541  programName = cache.value(0).name;
542  if (programName.isEmpty()) {
543  if (QCoreApplication::instance())
544  programName = QCoreApplication::instance()->applicationName().toLocal8Bit();
545  else
546  programName = "<unknown program name>";
547  }
548  s << programName.constData() << "(" << unsigned(getpid()) << ")";
549  }
550  if (printAreaName && (!printProcessInfo || areaName != programName)) {
551  if (printProcessInfo)
552  s << "/";
553  s << areaName.constData();
554  }
555 
556  if (m_indentString.hasLocalData()) {
557  s << m_indentString.localData()->toLatin1().constData();
558  }
559 
560  if (printFileLine) {
561  s << ' ' << file << ':' << line << ' ';
562  }
563 
564  if (funcinfo && printMethodName) {
565  if (colored) {
566  if (type <= QtDebugMsg)
567  s << "\033[0;34m"; //blue
568  else
569  s << "\033[0;31m"; //red
570  }
571 # ifdef Q_CC_GNU
572  // strip the function info down to the base function name
573  // note that this throws away the template definitions,
574  // the parameter types (overloads) and any const/volatile qualifiers
575  QByteArray info = funcinfo;
576  int pos = info.indexOf('(');
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) == ' ')
580  // that '(' we matched was actually the opening of a function-pointer
581  pos = info.indexOf('(', pos + 1);
582 
583  info.truncate(pos);
584  // gcc 4.1.2 don't put a space between the return type and
585  // the function name if the function is in an anonymous namespace
586  int index = 1;
587  forever {
588  index = info.indexOf("<unnamed>::", index);
589  if ( index == -1 )
590  break;
591 
592  if ( info.at(index-1) != ':' )
593  info.insert(index, ' ');
594 
595  index += strlen("<unnamed>::");
596  }
597  pos = info.lastIndexOf(' ');
598  if (pos != -1) {
599  int startoftemplate = info.lastIndexOf('<');
600  if (startoftemplate != -1 && pos > startoftemplate &&
601  pos < info.lastIndexOf(">::"))
602  // we matched a space inside this function's template definition
603  pos = info.lastIndexOf(' ', startoftemplate);
604  }
605 
606  if (pos + 1 == info.length())
607  // something went wrong, so gracefully bail out
608  s << " " << funcinfo;
609  else
610  s << " " << info.constData() + pos + 1;
611 # else
612  s << " " << funcinfo;
613 # endif
614  if(colored)
615  s << "\033[0m";
616  }
617 
618  s << ":";
619 #else
620  Q_UNUSED(funcinfo);
621  if (!areaName.isEmpty())
622  s << areaName.constData() << ':';
623 #endif
624  return s.space();
625  }
626 
627  QDebug stream(QtMsgType type, unsigned int area, const char *debugFile, int line,
628  const char *funcinfo)
629  {
630  static bool env_colored = (!qgetenv("KDE_COLOR_DEBUG").isEmpty());
631  static bool env_colors_on_any_fd = (!qgetenv("KDE_COLOR_DEBUG_ALWAYS").isEmpty());
632  Cache::Iterator it = areaData(type, area);
633  OutputMode mode = it->mode[level(type)];
634  Q_ASSERT(mode != Unknown);
635  QString file = it->logFileName[level(type)];
636  QByteArray areaName = it->name;
637 
638  if (areaName.isEmpty())
639  areaName = cache.value(0).name;
640 
641  bool colored=false;
642 
643  QDebug s(&devnull);
644  switch (mode) {
645  case FileOutput:
646  s = setupFileWriter(file);
647  break;
648  case MessageBoxOutput:
649  s = setupMessageBoxWriter(type, areaName);
650  break;
651  case SyslogOutput:
652  s = setupSyslogWriter(type);
653  break;
654  case NoOutput:
655  s = QDebug(&devnull);
656  return s; //no need to take the time to "print header" if we don't want to output anyway
657  break;
658  case Unknown: // should not happen
659  default: // QtOutput
660  s = setupQtWriter(type);
661 #ifndef Q_OS_WIN
662  //only color if the debug goes to a tty, unless env_colors_on_any_fd is set too.
663  colored = env_colored && (env_colors_on_any_fd || isatty(fileno(stderr)));
664 #endif
665  break;
666  }
667 
668  return printHeader(s, areaName, debugFile, line, funcinfo, type, colored);
669  }
670 
671  void writeGroupForNamedArea(const QByteArray& areaName, bool enabled)
672  {
673  // Ensure that this area name appears in kdebugrc, so that users (via kdebugdialog)
674  // can turn it off.
675  KConfig* cfgObj = configObject();
676  if (cfgObj) {
677  KConfigGroup cg(cfgObj, QString::fromUtf8(areaName));
678  const QString key = QString::fromLatin1("InfoOutput");
679  if (!cg.hasKey(key)) {
680  cg.writeEntry(key, int(enabled ? KDebugPrivate::QtOutput : KDebugPrivate::NoOutput));
681  cg.sync();
682  }
683  }
684  }
685 
686  QMutex mutex;
687  KConfig *config;
688  KDebugDBusIface *kDebugDBusIface;
689  Cache cache;
690  bool m_disableAll;
691  bool m_seenMainComponent; // false: area zero still contains qAppName
692  int m_nullOutputYesNoCache[8];
693 
694  KNoDebugStream devnull;
695  QThreadStorage<QString*> m_indentString;
696  QThreadStorage<KSyslogDebugStream*> syslogwriter;
697  QThreadStorage<KFileDebugStream*> filewriter;
698  QThreadStorage<KMessageBoxDebugStream*> messageboxwriter;
699  KLineEndStrippingDebugStream lineendstrippingwriter;
700 };
701 
702 K_GLOBAL_STATIC(KDebugPrivate, kDebug_data)
703 
704 #ifdef HAVE_BACKTRACE
705 static QString maybeDemangledName(char *name)
706 {
707 #ifdef HAVE_BACKTRACE_DEMANGLE
708  const int len = strlen(name);
709  QByteArray in = QByteArray::fromRawData(name, len);
710  const int mangledNameStart = in.indexOf("(_");
711  if (mangledNameStart >= 0) {
712  const int mangledNameEnd = in.indexOf('+', mangledNameStart + 2);
713  if (mangledNameEnd >= 0) {
714  int status;
715  // if we forget about this line and the one that undoes its effect we don't change the
716  // internal data of the QByteArray::fromRawData() ;)
717  name[mangledNameEnd] = 0;
718  char *demangled = abi::__cxa_demangle(name + mangledNameStart + 1, 0, 0, &status);
719  name[mangledNameEnd] = '+';
720  if (demangled) {
721  QString ret = QString::fromLatin1(name, mangledNameStart + 1) +
722  QString::fromLatin1(demangled) +
723  QString::fromLatin1(name + mangledNameEnd, len - mangledNameEnd);
724  free(demangled);
725  return ret;
726  }
727  }
728  }
729 #endif
730  return QString::fromLatin1(name);
731 }
732 #endif
733 
734 QString kRealBacktrace(int levels)
735 {
736  QString s;
737 #ifdef HAVE_BACKTRACE
738  void* trace[256];
739  int n = backtrace(trace, 256);
740  if (!n)
741  return s;
742  char** strings = backtrace_symbols (trace, n);
743 
744  if ( levels != -1 )
745  n = qMin( n, levels );
746  s = QLatin1String("[\n");
747 
748  for (int i = 0; i < n; ++i)
749  s += QString::number(i) + QLatin1String(": ") +
750  maybeDemangledName(strings[i]) + QLatin1Char('\n');
751  s += QLatin1String("]\n");
752  if (strings)
753  free (strings);
754 #endif
755  return s;
756 }
757 
758 QDebug kDebugDevNull()
759 {
760  return QDebug(&kDebug_data->devnull);
761 }
762 
763 QDebug kDebugStream(QtMsgType level, int area, const char *file, int line, const char *funcinfo)
764 {
765  if (kDebug_data.isDestroyed()) {
766  // we don't know what to return now...
767  qCritical().nospace() << "kDebugStream called after destruction (from "
768  << (funcinfo ? funcinfo : "")
769  << (file ? " file " : " unknown file")
770  << (file ? file :"")
771  << " line " << line << ")";
772  return QDebug(level);
773  }
774 
775  QMutexLocker locker(&kDebug_data->mutex);
776  return kDebug_data->stream(level, area, file, line, funcinfo);
777 }
778 
779 QDebug perror(QDebug s, KDebugTag)
780 {
781  return s << QString::fromLocal8Bit(strerror(errno));
782 }
783 
784 QDebug operator<<(QDebug s, const KDateTime &time)
785 {
786  if ( time.isDateOnly() )
787  s.nospace() << "KDateTime(" << qPrintable(time.toString(KDateTime::QtTextDate)) << ")";
788  else
789  s.nospace() << "KDateTime(" << qPrintable(time.toString(KDateTime::ISODate)) << ")";
790  return s.space();
791 }
792 
793 QDebug operator<<(QDebug s, const KUrl &url)
794 {
795  s.nospace() << "KUrl(" << url.prettyUrl() << ")";
796  return s.space();
797 }
798 
799 void kClearDebugConfig()
800 {
801  if (!kDebug_data) return;
802  KDebugPrivate* d = kDebug_data;
803  QMutexLocker locker(&d->mutex);
804  delete d->config;
805  d->config = 0;
806 
807  KDebugPrivate::Cache::Iterator it = d->cache.begin(),
808  end = d->cache.end();
809  for ( ; it != end; ++it)
810  it->clear();
811 
812  for (int i = 0; i < 8; i++) {
813  d->m_nullOutputYesNoCache[i] = -1;
814  }
815 }
816 
817 // static
818 bool KDebug::hasNullOutput(QtMsgType type,
819  bool condition,
820  int area,
821  bool enableByDefault)
822 {
823  if (!condition) {
824  return true;
825  }
826  if (kDebug_data.isDestroyed()) {
827  // kDebugStream() will generate a warning anyway, so we don't.
828  return false;
829  }
830  KDebugPrivate *const d = kDebug_data;
831  QMutexLocker locker(&d->mutex);
832 
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];
838  }
839  }
840  }
841 
842  KDebugPrivate::Cache::Iterator it = d->areaData(type, area, enableByDefault);
843  const bool ret = it->mode[d->level(type)] == KDebugPrivate::NoOutput;
844 
845  // cache result for next time...
846  if (type == QtDebugMsg) {
847  int *entries = d->m_nullOutputYesNoCache;
848  int idx = (qrand() % 4) * 2;
849  entries[idx] = area;
850  entries[idx + 1] = ret;
851  }
852 
853  return ret;
854 }
855 
856 int KDebug::registerArea(const QByteArray& areaName, bool enabled)
857 {
858  // TODO for optimization: static int s_lastAreaNumber = 1;
859  KDebugPrivate* d = kDebug_data;
860  QMutexLocker locker(&d->mutex);
861  int areaNumber = 1;
862  while (d->cache.contains(areaNumber)) {
863  ++areaNumber;
864  }
865  KDebugPrivate::Area areaData;
866  areaData.name = areaName;
867  //qDebug() << "Assigning area number" << areaNumber << "for name" << areaName;
868  d->cache.insert(areaNumber, areaData);
869  d->writeGroupForNamedArea(areaName, enabled);
870  return areaNumber;
871 }
872 
873 #ifndef KDE_NO_DEBUG_OUTPUT
874 
875 class KDebug::Block::Private
876 {
877 public:
878  QByteArray m_label;
879 };
880 
881 KDebug::Block::Block(const char* label, int area)
882  : m_label(0), m_area(area), d(0)
883 {
884  if (hasNullOutputQtDebugMsg(area)) {
885  d = 0; // remember, for the dtor
886  } else {
887  d = new Private;
888  d->m_label = label;
889  m_startTime.start();
890  kDebug(area) << "BEGIN:" << label;
891 
892  // The indent string is per thread
893  QThreadStorage<QString*> & indentString = kDebug_data->m_indentString;
894  if (!indentString.hasLocalData()) {
895  indentString.setLocalData(new QString);
896  }
897  *(indentString.localData()) += QLatin1String(" ");
898  }
899 }
900 
901 KDebug::Block::~Block()
902 {
903  if (d) {
904  const double duration = m_startTime.elapsed() / 1000.0;
905  QThreadStorage<QString*> & indentString = kDebug_data->m_indentString;
906  indentString.localData()->chop(2);
907 
908  // Print timing information, and a special message (DELAY) if the method took longer than 5s
909  if (duration < 5.0) {
910  kDebug(m_area)
911  << "END__:"
912  << d->m_label.constData()
913  << qPrintable(QString::fromLatin1("[Took: %3s]").arg(QString::number(duration, 'g', 2)));
914  } else {
915  kDebug(m_area)
916  << "END__:"
917  << d->m_label.constData()
918  << qPrintable(QString::fromLatin1("[DELAY Took (quite long) %3s]").arg(QString::number(duration, 'g', 2)));
919  }
920  delete d;
921  }
922 }
923 
924 #endif
QIODevice
KMessage::message
void message(KMessage::MessageType messageType, const QString &text, const QString &caption=QString())
Display a long message of a certain type.
Definition: kmessage.cpp:92
KMessage::Information
Information message.
Definition: kmessage.h:62
kde_kdebug_enable_dbus_interface
bool kde_kdebug_enable_dbus_interface
Definition: kdebug.cpp:109
QElapsedTimer::start
void start()
QMutex
qint64
QByteArray::toUInt
uint toUInt(bool *ok, int base) const
kdebugdbusiface_p.h
header
const char header[]
Definition: fake/kauth-policy-gen-polkit.cpp:26
perror
QDebug perror(QDebug s, KDebugTag)
Definition: kdebug.cpp:779
kdebug.h
kdatetime.h
Date/times with associated time zone.
kDebugDevNull
QDebug kDebugDevNull()
Definition: kdebug.cpp:758
kurl.h
QByteArray::trimmed
QByteArray trimmed() const
QByteArray
QByteArray::at
char at(int i) const
KDebug::hasNullOutput
static bool hasNullOutput(QtMsgType type, bool condition, int area, bool enableByDefault)
Definition: kdebug.cpp:818
QByteArray::lastIndexOf
int lastIndexOf(char ch, int from) const
K_GLOBAL_STATIC
#define K_GLOBAL_STATIC(TYPE, NAME)
This macro makes it easy to use non-POD types as global statics.
Definition: kglobal.h:221
KStandardDirs::locate
static QString locate(const char *type, const QString &filename, const KComponentData &cData=KGlobal::mainComponent())
This function is just for convenience.
Definition: kstandarddirs.cpp:2085
kconfig.h
QByteArray::isEmpty
bool isEmpty() const
KDateTime::QtTextDate
Same format as Qt::TextDate (i.e.
Definition: kdatetime.h:445
QDebug::nospace
QDebug & nospace()
KConfigBase::hasGroup
bool hasGroup(const QString &group) const
Returns true if the specified group is known about.
Definition: kconfigbase.cpp:29
KConfigBase::group
KConfigGroup group(const QByteArray &group)
Returns an object for the named subgroup.
Definition: kconfigbase.cpp:44
KDateTime::toString
QString toString(const QString &format) const
Returns the date/time as a string.
Definition: kdatetime.cpp:1434
QByteArray::fromRawData
QByteArray fromRawData(const char *data, int size)
QByteArray::insert
QByteArray & insert(int i, char ch)
KDateTime::isDateOnly
bool isDateOnly() const
Returns whether the instance represents a date/time or a date-only value.
Definition: kdatetime.cpp:832
QByteArray::length
int length() const
QIODevice::open
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
QIODevice::readData
virtual qint64 readData(char *data, qint64 maxSize)=0
klocale.h
QIODevice::isSequential
virtual bool isSequential() const
QFile
KUrl
Represents and parses a URL.
Definition: kurl.h:111
KGlobal::config
KSharedConfigPtr config()
Returns the general config object.
Definition: kglobal.cpp:139
QThreadStorage::setLocalData
void setLocalData(T data)
QByteArray::indexOf
int indexOf(char ch, int from) const
kglobal.h
QString::number
QString number(int n, int base)
QString::fromLocal8Bit
QString fromLocal8Bit(const char *str, int size)
QThreadStorage::hasLocalData
bool hasLocalData() const
QString::fromUtf8
QString fromUtf8(const char *str, int size)
KConfig::NoGlobals
Cascade to system settings, but omit user's globals.
Definition: kconfig.h:98
QHash< unsigned int, Area >
operator<<
QDebug operator<<(QDebug s, const KDateTime &time)
Definition: kdebug.cpp:784
kClearDebugConfig
void kClearDebugConfig()
Definition: kdebug.cpp:799
kcmdlineargs.h
QByteArray::constData
const char * constData() const
KDebug::registerArea
static int registerArea(const QByteArray &areaName, bool enabled=true)
Definition: kdebug.cpp:856
KFileSystemType::Unknown
Definition: kfilesystemtype_p.h:29
QByteArray::truncate
void truncate(int pos)
QCoreApplication::instance
QCoreApplication * instance()
QThreadStorage::localData
T & localData()
KComponentData::componentName
QString componentName() const
Returns the name of the component.
Definition: kcomponentdata.cpp:226
QString
QByteArray::mid
QByteArray mid(int pos, int len) const
KDebug::hasNullOutputQtDebugMsg
static bool hasNullOutputQtDebugMsg(int area=KDE_DEFAULT_DEBUG_AREA)
Definition: kdebug.h:271
maybeDemangledName
static QString maybeDemangledName(char *name)
Definition: kdebug.cpp:705
QThreadStorage< QString * >
QDebug::space
QDebug & space()
KDateTime
A class representing a date and time with an associated time zone.
Definition: kdatetime.h:171
QLatin1Char
QDebug
KConfigGroup
A class for one specific group in a KConfig object.
Definition: kconfiggroup.h:53
QIODevice::readLineData
virtual qint64 readLineData(char *data, qint64 maxSize)
KConfig
The central class of the KDE configuration data system.
Definition: kconfig.h:70
QByteArray::left
QByteArray left(int len) const
QDateTime::currentDateTime
QDateTime currentDateTime()
QTest::toString
char * toString(const T &value)
QLatin1String
QMutexLocker
kstandarddirs.h
QIODevice::writeData
virtual qint64 writeData(const char *data, qint64 maxSize)=0
KDateTime::ISODate
ISO 8601 format, i.e.
Definition: kdatetime.h:421
KGlobal::mainComponent
const KComponentData & mainComponent()
Returns the global component data.
Definition: kglobal.cpp:145
KGlobal::hasMainComponent
bool hasMainComponent()
Definition: kglobal.cpp:151
kDebugStream
QDebug kDebugStream(QtMsgType level, int area, const char *file, int line, const char *funcinfo)
Definition: kdebug.cpp:763
KDebug::Block::Block
Block(const char *label, int area=KDE_DEFAULT_DEBUG_AREA)
Definition: kdebug.cpp:881
QString::fromLatin1
QString fromLatin1(const char *str, int size)
kDebug
#define kDebug
Definition: kdebug.h:316
kcomponentdata.h
KDebugDBusIface
D-Bus interface to KDebug.
Definition: kdebugdbusiface_p.h:30
KDebugTag
Definition: kdebug.h:201
kmessage.h
QHash< unsigned int, Area >::Iterator
typedef Iterator
KConfigGroup::readEntry
T readEntry(const QString &key, const T &aDefault) const
Reads the value of an entry specified by pKey in the current group.
Definition: kconfiggroup.h:248
KDebug::Block::~Block
~Block()
Definition: kdebug.cpp:901
KUrl::prettyUrl
QString prettyUrl(AdjustPathOption trailing=LeaveTrailingSlash) const
Returns the URL as string in human-friendly format.
Definition: kurl.cpp:1086
kconfiggroup.h
QCoreApplication::applicationName
applicationName
kRealBacktrace
QString kRealBacktrace(int levels)
Definition: kdebug.cpp:734
QString::toUtf8
QByteArray toUtf8() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:22:11 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

Skip menu "KDECore"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal