1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtCore module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
44 #include "qbytearray.h"
46 #include "qvarlengtharray.h"
54 \class QMessageLogContext
56 \brief The QMessageLogContext class provides additional information about a log message.
59 The class provides information about the source code location a qDebug(), qWarning(),
60 qCritical() or qFatal() message was generated.
62 \sa QMessageLogger, QMessageHandler, qInstallMessageHandler()
68 \brief The QMessageLogger class generates log messages.
71 QMessageLogger is used to generate messages for the Qt logging framework. Most of the time
72 is transparently used through the qDebug(), qWarning(), qCritical, or qFatal() functions,
73 which are actually macros that expand to QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).debug()
76 One example of direct use is to forward errors that stem from a scripting language, e.g. QML:
78 \snippet doc/src/snippets/code/qlogging/qlogging.cpp 1
80 \sa QMessageLogContext, qDebug(), qWarning(), qCritical(), qFatal()
83 #if !defined(QT_NO_EXCEPTIONS)
86 Uses a local buffer to output the message. Not locale safe + cuts off
87 everything after character 255, but will work in out of memory situations.
89 static void qEmergencyOut(QtMsgType msgType, const char *msg, va_list ap)
91 char emergency_buf[256] = { '\0' };
92 emergency_buf[255] = '\0';
94 qvsnprintf(emergency_buf, 255, msg, ap);
95 QMessageLogContext context;
96 qt_message_output(msgType, context, emergency_buf);
103 static void qt_message(QtMsgType msgType, const QMessageLogContext &context, const char *msg,
106 #if !defined(QT_NO_EXCEPTIONS)
107 if (std::uncaught_exception()) {
108 qEmergencyOut(msgType, msg, ap);
115 buf = QString().vsprintf(msg, ap).toLocal8Bit();
116 } QT_CATCH(const std::bad_alloc &) {
117 #if !defined(QT_NO_EXCEPTIONS)
118 qEmergencyOut(msgType, msg, ap);
119 // don't rethrow - we use qWarning and friends in destructors.
124 qt_message_output(msgType, context, buf.constData());
129 \fn qDebug(const char *message, ...)
132 Calls the message handler with the debug message \a msg. If no
133 message handler has been installed, the message is printed to
134 stderr. Under Windows, the message is sent to the console, if it is a
135 console application; otherwise, it is sent to the debugger. This
136 function does nothing if \c QT_NO_DEBUG_OUTPUT was defined
139 If you pass the function a format string and a list of arguments,
140 it works in similar way to the C printf() function. The format
141 should be a Latin-1 string.
145 \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 24
147 If you include \c <QtDebug>, a more convenient syntax is also
150 \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 25
152 With this syntax, the function returns a QDebug object that is
153 configured to use the QtDebugMsg message type. It automatically
154 puts a single space between each item, and outputs a newline at
155 the end. It supports many C++ and Qt types.
157 To suppress the output at run-time, install your own message handler
158 with qInstallMessageHandler().
160 \sa qWarning(), qCritical(), qFatal(), qInstallMessageHandler(),
161 {Debugging Techniques}
164 void QMessageLogger::debug(const char *msg, ...)
167 va_start(ap, msg); // use variable arg list
168 qt_message(QtDebugMsg, context, msg, ap);
172 #ifndef QT_NO_DEBUG_STREAM
174 QDebug QMessageLogger::debug()
176 QDebug dbg = QDebug(QtDebugMsg);
177 QMessageLogContext &ctxt = dbg.stream->context;
178 ctxt.file = context.file;
179 ctxt.line = context.line;
180 ctxt.function = context.function;
184 QNoDebug QMessageLogger::noDebug()
193 \fn qWarning(const char *message, ...)
196 Calls the message handler with the warning message \a msg. If no
197 message handler has been installed, the message is printed to
198 stderr. Under Windows, the message is sent to the debugger. This
199 function does nothing if \c QT_NO_WARNING_OUTPUT was defined
200 during compilation; it exits if the environment variable \c
201 QT_FATAL_WARNINGS is defined.
203 This function takes a format string and a list of arguments,
204 similar to the C printf() function. The format should be a Latin-1
208 \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 26
210 If you include <QtDebug>, a more convenient syntax is
213 \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 27
215 This syntax inserts a space between each item, and
216 appends a newline at the end.
218 To suppress the output at runtime, install your own message handler
219 with qInstallMessageHandler().
221 \sa qDebug(), qCritical(), qFatal(), qInstallMessageHandler(),
222 {Debugging Techniques}
225 void QMessageLogger::warning(const char *msg, ...)
228 va_start(ap, msg); // use variable arg list
229 qt_message(QtWarningMsg, context, msg, ap);
233 #ifndef QT_NO_DEBUG_STREAM
234 QDebug QMessageLogger::warning()
236 QDebug dbg = QDebug(QtWarningMsg);
237 QMessageLogContext &ctxt = dbg.stream->context;
238 ctxt.file = context.file;
239 ctxt.line = context.line;
240 ctxt.function = context.function;
247 \fn qCritical(const char *message, ...)
250 Calls the message handler with the critical message \a msg. If no
251 message handler has been installed, the message is printed to
252 stderr. Under Windows, the message is sent to the debugger.
254 This function takes a format string and a list of arguments,
255 similar to the C printf() function. The format should be a Latin-1
259 \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 28
261 If you include <QtDebug>, a more convenient syntax is
264 \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 29
266 A space is inserted between the items, and a newline is
269 To suppress the output at runtime, install your own message handler
270 with qInstallMessageHandler().
272 \sa qDebug(), qWarning(), qFatal(), qInstallMessageHandler(),
273 {Debugging Techniques}
276 void QMessageLogger::critical(const char *msg, ...)
279 va_start(ap, msg); // use variable arg list
280 qt_message(QtCriticalMsg, context, msg, ap);
284 #ifndef QT_NO_DEBUG_STREAM
285 QDebug QMessageLogger::critical()
287 QDebug dbg = QDebug(QtCriticalMsg);
288 QMessageLogContext &ctxt = dbg.stream->context;
289 ctxt.file = context.file;
290 ctxt.line = context.line;
291 ctxt.function = context.function;
298 \fn qFatal(const char *message, ...)
301 Calls the message handler with the fatal message \a msg. If no
302 message handler has been installed, the message is printed to
303 stderr. Under Windows, the message is sent to the debugger.
305 If you are using the \bold{default message handler} this function will
306 abort on Unix systems to create a core dump. On Windows, for debug builds,
307 this function will report a _CRT_ERROR enabling you to connect a debugger
310 This function takes a format string and a list of arguments,
311 similar to the C printf() function.
314 \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 30
316 To suppress the output at runtime, install your own message handler
317 with qInstallMessageHandler().
319 \sa qDebug(), qCritical(), qWarning(), qInstallMessageHandler(),
320 {Debugging Techniques}
323 void QMessageLogger::fatal(const char *msg, ...)
326 va_start(ap, msg); // use variable arg list
327 qt_message(QtFatalMsg, context, msg, ap);
334 Q_AUTOTEST_EXPORT QByteArray qCleanupFuncinfo(QByteArray info)
336 // Strip the function info down to the base function name
337 // note that this throws away the template definitions,
338 // the parameter types (overloads) and any const/volatile qualifiers.
345 // skip trailing [with XXX] for templates (gcc)
346 pos = info.size() - 1;
347 if (info.endsWith(']')) {
349 if (info.at(pos) == '[')
354 // operator names with '(', ')', '<', '>' in it
355 static const char operator_call[] = "operator()";
356 static const char operator_lessThan[] = "operator<";
357 static const char operator_greaterThan[] = "operator>";
358 static const char operator_lessThanEqual[] = "operator<=";
359 static const char operator_greaterThanEqual[] = "operator>=";
361 // canonize operator names
362 info.replace("operator ", "operator");
364 // remove argument list
367 pos = info.lastIndexOf(')');
369 // Don't know how to parse this function name
373 // find the beginning of the argument list
376 while (pos && parencount) {
377 if (info.at(pos) == ')')
379 else if (info.at(pos) == '(')
386 info.truncate(++pos);
388 if (info.at(pos - 1) == ')') {
389 if (info.indexOf(operator_call) == pos - (int)strlen(operator_call))
392 // this function returns a pointer to a function
393 // and we matched the arguments of the return type's parameter list
395 info.remove(0, info.indexOf('('));
403 // find the beginning of the function name
405 int templatecount = 0;
408 // make sure special characters in operator names are kept
410 switch (info.at(pos)) {
412 if (info.indexOf(operator_call) == pos - (int)strlen(operator_call) + 1)
416 if (info.indexOf(operator_lessThan) == pos - (int)strlen(operator_lessThan) + 1)
420 if (info.indexOf(operator_greaterThan) == pos - (int)strlen(operator_greaterThan) + 1)
424 int operatorLength = (int)strlen(operator_lessThanEqual);
425 if (info.indexOf(operator_lessThanEqual) == pos - operatorLength + 1)
427 else if (info.indexOf(operator_greaterThanEqual) == pos - operatorLength + 1)
437 if (parencount < 0 || templatecount < 0)
440 char c = info.at(pos);
449 else if (c == ' ' && templatecount == 0 && parencount == 0)
454 info = info.mid(pos + 1);
456 // remove trailing '*', '&' that are part of the return argument
457 while ((info.at(0) == '*')
458 || (info.at(0) == '&'))
461 // we have the full function name now.
462 // clean up the templates
463 while ((pos = info.lastIndexOf('>')) != -1) {
464 if (!info.contains('<'))
467 // find the matching close
471 while (pos && templatecount) {
472 register char c = info.at(pos);
480 info.remove(pos, end - pos + 1);
486 // tokens as recognized in QT_MESSAGE_PATTERN
487 static const char typeTokenC[] = "%{type}";
488 static const char messageTokenC[] = "%{message}";
489 static const char fileTokenC[] = "%{file}";
490 static const char lineTokenC[] = "%{line}";
491 static const char functionTokenC[] = "%{function}";
492 static const char emptyTokenC[] = "";
494 struct QMessagePattern {
498 // 0 terminated arrays of literal tokens / literal or placeholder tokens
499 const char **literals;
503 QMessagePattern::QMessagePattern()
505 QString pattern = QString::fromLocal8Bit(qgetenv("QT_MESSAGE_PATTERN"));
506 if (pattern.isEmpty()) {
507 pattern = QLatin1String("%{message}");
511 QList<QString> lexemes;
513 bool inPlaceholder = false;
514 for (int i = 0; i < pattern.size(); ++i) {
515 const QChar c = pattern.at(i);
516 if ((c == QLatin1Char('%'))
518 if ((i + 1 < pattern.size())
519 && pattern.at(i + 1) == QLatin1Char('{')) {
520 // beginning of placeholder
521 if (!lexeme.isEmpty()) {
522 lexemes.append(lexeme);
525 inPlaceholder = true;
531 if ((c == QLatin1Char('}') && inPlaceholder)) {
532 // end of placeholder
533 lexemes.append(lexeme);
535 inPlaceholder = false;
538 if (!lexeme.isEmpty())
539 lexemes.append(lexeme);
542 QVarLengthArray<const char*> literalsVar;
543 tokens = new const char*[lexemes.size() + 1];
544 tokens[lexemes.size()] = 0;
546 for (int i = 0; i < lexemes.size(); ++i) {
547 const QString lexeme = lexemes.at(i);
548 if (lexeme.startsWith(QLatin1String("%{"))
549 && lexeme.endsWith(QLatin1Char('}'))) {
551 if (lexeme == QLatin1String(typeTokenC)) {
552 tokens[i] = typeTokenC;
553 } else if (lexeme == QLatin1String(messageTokenC))
554 tokens[i] = messageTokenC;
555 else if (lexeme == QLatin1String(fileTokenC))
556 tokens[i] = fileTokenC;
557 else if (lexeme == QLatin1String(lineTokenC))
558 tokens[i] = lineTokenC;
559 else if (lexeme == QLatin1String(functionTokenC))
560 tokens[i] = functionTokenC;
562 fprintf(stderr, "%s\n",
563 QString::fromLatin1("QT_MESSAGE_PATTERN: Unknown placeholder %1\n"
564 ).arg(lexeme).toLocal8Bit().constData());
566 tokens[i] = emptyTokenC;
569 char *literal = new char[lexeme.size() + 1];
570 strncpy(literal, lexeme.toLocal8Bit().constData(), lexeme.size());
571 literal[lexeme.size()] = '\0';
572 literalsVar.append(literal);
576 literals = new const char*[literalsVar.size() + 1];
577 literals[literalsVar.size()] = 0;
578 memcpy(literals, literalsVar.constData(), literalsVar.size() * sizeof(const char*));
581 QMessagePattern::~QMessagePattern()
583 for (int i = 0; literals[i] != 0; ++i)
584 delete [] literals[i];
591 Q_GLOBAL_STATIC(QMessagePattern, qMessagePattern)
596 Q_CORE_EXPORT QByteArray qMessageFormatString(QtMsgType type, const QMessageLogContext &context,
601 QMessagePattern *pattern = qMessagePattern();
603 // after destruction of static QMessagePattern instance
605 message.append('\n');
609 // we do not convert file, function, line literals to local encoding due to overhead
610 for (int i = 0; pattern->tokens[i] != 0; ++i) {
611 const char *token = pattern->tokens[i];
612 if (token == messageTokenC) {
614 } else if (token == typeTokenC) {
616 case QtDebugMsg: message.append("debug"); break;
617 case QtWarningMsg: message.append("warning"); break;
618 case QtCriticalMsg:message.append("critical"); break;
619 case QtFatalMsg: message.append("fatal"); break;
621 } else if (token == fileTokenC) {
623 message.append(context.file);
625 message.append("unknown");
626 } else if (token == lineTokenC) {
627 message.append(QString::number(context.line).toLatin1().constData());
628 } else if (token == functionTokenC) {
629 if (context.function)
630 message.append(qCleanupFuncinfo(context.function));
632 message.append("unknown");
634 message.append(token);
637 message.append('\n');
641 static QtMsgHandler msgHandler = 0; // pointer to debug handler (without context)
642 static QMessageHandler messageHandler = 0; // pointer to debug handler (with context)
647 static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &context,
650 QByteArray logMessage = qMessageFormatString(type, context, buf);
651 #if defined(Q_OS_WINCE)
652 QString fstr = QString::fromLocal8Bit(logMessage);
653 OutputDebugString(reinterpret_cast<const wchar_t *> (fstr.utf16()));
655 fprintf(stderr, "%s", logMessage.constData());
663 static void qDefaultMsgHandler(QtMsgType type, const char *buf)
665 QMessageLogContext emptyContext;
666 qDefaultMessageHandler(type, emptyContext, buf);
672 void qt_message_output(QtMsgType msgType, const QMessageLogContext &context, const char *buf)
675 msgHandler = qDefaultMsgHandler;
677 messageHandler = qDefaultMessageHandler;
679 // prefer new message handler over the old one
680 if (msgHandler == qDefaultMsgHandler
681 || messageHandler != qDefaultMessageHandler) {
682 (*messageHandler)(msgType, context, buf);
684 (*msgHandler)(msgType, buf);
687 if (msgType == QtFatalMsg
688 || (msgType == QtWarningMsg
689 && (!qgetenv("QT_FATAL_WARNINGS").isNull())) ) {
691 #if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR)
692 // get the current report mode
693 int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW);
694 _CrtSetReportMode(_CRT_ERROR, reportMode);
695 #if !defined(Q_OS_WINCE)
696 int ret = _CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, QT_VERSION_STR, buf);
698 int ret = _CrtDbgReportW(_CRT_ERROR, _CRT_WIDE(__FILE__),
699 __LINE__, _CRT_WIDE(QT_VERSION_STR),
700 reinterpret_cast<const wchar_t *> (
701 QString::fromLatin1(buf).utf16()));
703 if (ret == 0 && reportMode & _CRTDBG_MODE_WNDW)
709 #if (defined(Q_OS_UNIX) || defined(Q_CC_MINGW))
710 abort(); // trap; generates core dump
712 exit(1); // goodbye cruel world
717 void qErrnoWarning(const char *msg, ...)
719 // qt_error_string() will allocate anyway, so we don't have
720 // to be careful here (like we do in plain qWarning())
725 buf.vsprintf(msg, ap);
728 QMessageLogger().critical("%s (%s)", buf.toLocal8Bit().constData(),
729 qt_error_string(-1).toLocal8Bit().constData());
732 void qErrnoWarning(int code, const char *msg, ...)
734 // qt_error_string() will allocate anyway, so we don't have
735 // to be careful here (like we do in plain qWarning())
740 buf.vsprintf(msg, ap);
743 QMessageLogger().critical("%s (%s)", buf.toLocal8Bit().constData(),
744 qt_error_string(code).toLocal8Bit().constData());
747 #if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB)
748 extern bool usingWinMain;
749 extern Q_CORE_EXPORT void qWinMsgHandler(QtMsgType t, const char *str);
750 extern Q_CORE_EXPORT void qWinMessageHandler(QtMsgType t, const QMessageLogContext &context,
755 \typedef QtMsgHandler
759 This is a typedef for a pointer to a function with the following
762 \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 7
764 This typedef is deprecated, you should use QMessageHandler instead.
765 \sa QtMsgType, QMessageHandler, qInstallMsgHandler(), qInstallMessageHandler()
769 \typedef QMessageHandler
773 This is a typedef for a pointer to a function with the following
776 \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 49
778 \sa QtMsgType, qInstallMessageHandler()
782 \fn QMessageHandler qInstallMessageHandler(QMessageHandler handler)
786 Installs a Qt message \a handler which has been defined
787 previously. Returns a pointer to the previous message handler
790 The message handler is a function that prints out debug messages,
791 warnings, critical and fatal error messages. The Qt library (debug
792 mode) contains hundreds of warning messages that are printed
793 when internal errors (usually invalid function arguments)
794 occur. Qt built in release mode also contains such warnings unless
795 QT_NO_WARNING_OUTPUT and/or QT_NO_DEBUG_OUTPUT have been set during
796 compilation. If you implement your own message handler, you get total
797 control of these messages.
799 The default message handler prints the message to the standard
800 output under X11 or to the debugger under Windows. If it is a
801 fatal message, the application aborts immediately.
803 Only one message handler can be defined, since this is usually
804 done on an application-wide basis to control debug output.
806 To restore the message handler, call \c qInstallMessageHandler(0).
810 \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 23
812 \sa qDebug(), qWarning(), qCritical(), qFatal(), QtMsgType,
813 {Debugging Techniques}
816 QMessageHandler qInstallMessageHandler(QMessageHandler h)
819 messageHandler = qDefaultMessageHandler;
820 QMessageHandler old = messageHandler;
822 #if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB)
823 if (!messageHandler && usingWinMain)
824 messageHandler = qWinMessageHandler;
830 \fn QtMsgHandler qInstallMsgHandler(QtMsgHandler handler)
834 Installs a Qt message \a handler which has been defined
835 previously. This method is deprecated, use qInstallMessageHandler
837 \sa QtMsgHandler, qInstallMessageHandler
840 QtMsgHandler qInstallMsgHandler(QtMsgHandler h)
842 //if handler is 0, set it to the
843 //default message handler
845 msgHandler = qDefaultMsgHandler;
846 QtMsgHandler old = msgHandler;
848 #if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB)
849 if (!msgHandler && usingWinMain)
850 msgHandler = qWinMsgHandler;