Reshuffle code between qglobal, qlogging
[profile/ivi/qtbase.git] / src / corelib / global / qlogging.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
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.
16 **
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.
20 **
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.
28 **
29 ** Other Usage
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.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qlogging.h"
43 #include "qlist.h"
44 #include "qbytearray.h"
45 #include "qstring.h"
46 #include "qvarlengtharray.h"
47 #include "qdebug.h"
48
49 #include <stdio.h>
50
51 QT_BEGIN_NAMESPACE
52
53 /*!
54     \class QMessageLogContext
55     \relates <QtGlobal>
56     \brief The QMessageLogContext class provides additional information about a log message.
57     \since 5.0
58
59     The class provides information about the source code location a qDebug(), qWarning(),
60     qCritical() or qFatal() message was generated.
61
62     \sa QMessageLogger, QMessageHandler, qInstallMessageHandler()
63 */
64
65 /*!
66     \class QMessageLogger
67     \relates <QtGlobal>
68     \brief The QMessageLogger class generates log messages.
69     \since 5.0
70
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()
74     et al.
75
76     One example of direct use is to forward errors that stem from a scripting language, e.g. QML:
77
78     \snippet doc/src/snippets/code/qlogging/qlogging.cpp 1
79
80     \sa QMessageLogContext, qDebug(), qWarning(), qCritical(), qFatal()
81 */
82
83 #if !defined(QT_NO_EXCEPTIONS)
84 /*!
85     \internal
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.
88 */
89 static void qEmergencyOut(QtMsgType msgType, const char *msg, va_list ap)
90 {
91     char emergency_buf[256] = { '\0' };
92     emergency_buf[255] = '\0';
93     if (msg)
94         qvsnprintf(emergency_buf, 255, msg, ap);
95     QMessageLogContext context;
96     qt_message_output(msgType, context, emergency_buf);
97 }
98 #endif
99
100 /*!
101     \internal
102 */
103 static void qt_message(QtMsgType msgType, const QMessageLogContext &context, const char *msg,
104                        va_list ap)
105 {
106 #if !defined(QT_NO_EXCEPTIONS)
107     if (std::uncaught_exception()) {
108         qEmergencyOut(msgType, msg, ap);
109         return;
110     }
111 #endif
112     QByteArray buf;
113     if (msg) {
114         QT_TRY {
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.
120             return;
121 #endif
122         }
123     }
124     qt_message_output(msgType, context, buf.constData());
125 }
126
127 #undef qDebug
128 /*!
129     \fn qDebug(const char *message, ...)
130     \relates <QtGlobal>
131
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
137     during compilation.
138
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.
142
143     Example:
144
145     \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 24
146
147     If you include \c <QtDebug>, a more convenient syntax is also
148     available:
149
150     \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 25
151
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.
156
157     To suppress the output at run-time, install your own message handler
158     with qInstallMessageHandler().
159
160     \sa qWarning(), qCritical(), qFatal(), qInstallMessageHandler(),
161         {Debugging Techniques}
162 */
163
164 void QMessageLogger::debug(const char *msg, ...)
165 {
166     va_list ap;
167     va_start(ap, msg); // use variable arg list
168     qt_message(QtDebugMsg, context, msg, ap);
169     va_end(ap);
170 }
171
172 #ifndef QT_NO_DEBUG_STREAM
173
174 QDebug QMessageLogger::debug()
175 {
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;
181     return dbg;
182 }
183
184 QNoDebug QMessageLogger::noDebug()
185 {
186     return QNoDebug();
187 }
188
189 #endif
190
191 #undef qWarning
192 /*!
193     \fn qWarning(const char *message, ...)
194     \relates <QtGlobal>
195
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.
202
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
205     string.
206
207     Example:
208     \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 26
209
210     If you include <QtDebug>, a more convenient syntax is
211     also available:
212
213     \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 27
214
215     This syntax inserts a space between each item, and
216     appends a newline at the end.
217
218     To suppress the output at runtime, install your own message handler
219     with qInstallMessageHandler().
220
221     \sa qDebug(), qCritical(), qFatal(), qInstallMessageHandler(),
222         {Debugging Techniques}
223 */
224
225 void QMessageLogger::warning(const char *msg, ...)
226 {
227     va_list ap;
228     va_start(ap, msg); // use variable arg list
229     qt_message(QtWarningMsg, context, msg, ap);
230     va_end(ap);
231 }
232
233 #ifndef QT_NO_DEBUG_STREAM
234 QDebug QMessageLogger::warning()
235 {
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;
241     return dbg;
242 }
243 #endif
244
245 #undef qCritical
246 /*!
247     \fn qCritical(const char *message, ...)
248     \relates <QtGlobal>
249
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.
253
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
256     string.
257
258     Example:
259     \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 28
260
261     If you include <QtDebug>, a more convenient syntax is
262     also available:
263
264     \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 29
265
266     A space is inserted between the items, and a newline is
267     appended at the end.
268
269     To suppress the output at runtime, install your own message handler
270     with qInstallMessageHandler().
271
272     \sa qDebug(), qWarning(), qFatal(), qInstallMessageHandler(),
273         {Debugging Techniques}
274 */
275
276 void QMessageLogger::critical(const char *msg, ...)
277 {
278     va_list ap;
279     va_start(ap, msg); // use variable arg list
280     qt_message(QtCriticalMsg, context, msg, ap);
281     va_end(ap);
282 }
283
284 #ifndef QT_NO_DEBUG_STREAM
285 QDebug QMessageLogger::critical()
286 {
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;
292     return dbg;
293 }
294 #endif
295
296 #undef qFatal
297 /*!
298     \fn qFatal(const char *message, ...)
299     \relates <QtGlobal>
300
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.
304
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
308     to the application.
309
310     This function takes a format string and a list of arguments,
311     similar to the C printf() function.
312
313     Example:
314     \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 30
315
316     To suppress the output at runtime, install your own message handler
317     with qInstallMessageHandler().
318
319     \sa qDebug(), qCritical(), qWarning(), qInstallMessageHandler(),
320         {Debugging Techniques}
321 */
322
323 void QMessageLogger::fatal(const char *msg, ...)
324 {
325     va_list ap;
326     va_start(ap, msg); // use variable arg list
327     qt_message(QtFatalMsg, context, msg, ap);
328     va_end(ap);
329 }
330
331 /*!
332     \internal
333 */
334 Q_AUTOTEST_EXPORT QByteArray qCleanupFuncinfo(QByteArray info)
335 {
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.
339
340     if (info.isEmpty())
341         return info;
342
343     int pos;
344
345     // skip trailing [with XXX] for templates (gcc)
346     pos = info.size() - 1;
347     if (info.endsWith(']')) {
348         while (--pos) {
349             if (info.at(pos) == '[')
350                 info.truncate(pos);
351         }
352     }
353
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>=";
360
361     // canonize operator names
362     info.replace("operator ", "operator");
363
364     // remove argument list
365     forever {
366         int parencount = 0;
367         pos = info.lastIndexOf(')');
368         if (pos == -1) {
369             // Don't know how to parse this function name
370             return info;
371         }
372
373         // find the beginning of the argument list
374         --pos;
375         ++parencount;
376         while (pos && parencount) {
377             if (info.at(pos) == ')')
378                 ++parencount;
379             else if (info.at(pos) == '(')
380                 --parencount;
381             --pos;
382         }
383         if (parencount != 0)
384             return info;
385
386         info.truncate(++pos);
387
388         if (info.at(pos - 1) == ')') {
389             if (info.indexOf(operator_call) == pos - (int)strlen(operator_call))
390                 break;
391
392             // this function returns a pointer to a function
393             // and we matched the arguments of the return type's parameter list
394             // try again
395             info.remove(0, info.indexOf('('));
396             info.chop(1);
397             continue;
398         } else {
399             break;
400         }
401     }
402
403     // find the beginning of the function name
404     int parencount = 0;
405     int templatecount = 0;
406     --pos;
407
408     // make sure special characters in operator names are kept
409     if (pos > -1) {
410         switch (info.at(pos)) {
411         case ')':
412             if (info.indexOf(operator_call) == pos - (int)strlen(operator_call) + 1)
413                 pos -= 2;
414             break;
415         case '<':
416             if (info.indexOf(operator_lessThan) == pos - (int)strlen(operator_lessThan) + 1)
417                 --pos;
418             break;
419         case '>':
420             if (info.indexOf(operator_greaterThan) == pos - (int)strlen(operator_greaterThan) + 1)
421                 --pos;
422             break;
423         case '=': {
424             int operatorLength = (int)strlen(operator_lessThanEqual);
425             if (info.indexOf(operator_lessThanEqual) == pos - operatorLength + 1)
426                 pos -= 2;
427             else if (info.indexOf(operator_greaterThanEqual) == pos - operatorLength + 1)
428                 pos -= 2;
429             break;
430         }
431         default:
432             break;
433         }
434     }
435
436     while (pos > -1) {
437         if (parencount < 0 || templatecount < 0)
438             return info;
439
440         char c = info.at(pos);
441         if (c == ')')
442             ++parencount;
443         else if (c == '(')
444             --parencount;
445         else if (c == '>')
446             ++templatecount;
447         else if (c == '<')
448             --templatecount;
449         else if (c == ' ' && templatecount == 0 && parencount == 0)
450             break;
451
452         --pos;
453     }
454     info = info.mid(pos + 1);
455
456     // remove trailing '*', '&' that are part of the return argument
457     while ((info.at(0) == '*')
458            || (info.at(0) == '&'))
459         info = info.mid(1);
460
461     // we have the full function name now.
462     // clean up the templates
463     while ((pos = info.lastIndexOf('>')) != -1) {
464         if (!info.contains('<'))
465             break;
466
467         // find the matching close
468         int end = pos;
469         templatecount = 1;
470         --pos;
471         while (pos && templatecount) {
472             register char c = info.at(pos);
473             if (c == '>')
474                 ++templatecount;
475             else if (c == '<')
476                 --templatecount;
477             --pos;
478         }
479         ++pos;
480         info.remove(pos, end - pos + 1);
481     }
482
483     return info;
484 }
485
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[] = "";
493
494 struct QMessagePattern {
495     QMessagePattern();
496     ~QMessagePattern();
497
498     // 0 terminated arrays of literal tokens / literal or placeholder tokens
499     const char **literals;
500     const char **tokens;
501 };
502
503 QMessagePattern::QMessagePattern()
504 {
505     QString pattern = QString::fromLocal8Bit(qgetenv("QT_MESSAGE_PATTERN"));
506     if (pattern.isEmpty()) {
507         pattern = QLatin1String("%{message}");
508     }
509
510     // scanner
511     QList<QString> lexemes;
512     QString lexeme;
513     bool inPlaceholder = false;
514     for (int i = 0; i < pattern.size(); ++i) {
515         const QChar c = pattern.at(i);
516         if ((c == QLatin1Char('%'))
517                 && !inPlaceholder) {
518             if ((i + 1 < pattern.size())
519                     && pattern.at(i + 1) == QLatin1Char('{')) {
520                 // beginning of placeholder
521                 if (!lexeme.isEmpty()) {
522                     lexemes.append(lexeme);
523                     lexeme.clear();
524                 }
525                 inPlaceholder = true;
526             }
527         }
528
529         lexeme.append(c);
530
531         if ((c == QLatin1Char('}') && inPlaceholder)) {
532             // end of placeholder
533             lexemes.append(lexeme);
534             lexeme.clear();
535             inPlaceholder = false;
536         }
537     }
538     if (!lexeme.isEmpty())
539         lexemes.append(lexeme);
540
541     // tokenizer
542     QVarLengthArray<const char*> literalsVar;
543     tokens = new const char*[lexemes.size() + 1];
544     tokens[lexemes.size()] = 0;
545
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('}'))) {
550             // placeholder
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;
561             else {
562                 fprintf(stderr, "%s\n",
563                         QString::fromLatin1("QT_MESSAGE_PATTERN: Unknown placeholder %1\n"
564                                             ).arg(lexeme).toLocal8Bit().constData());
565                 fflush(stderr);
566                 tokens[i] = emptyTokenC;
567             }
568         } else {
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);
573             tokens[i] = literal;
574         }
575     }
576     literals = new const char*[literalsVar.size() + 1];
577     literals[literalsVar.size()] = 0;
578     memcpy(literals, literalsVar.constData(), literalsVar.size() * sizeof(const char*));
579 }
580
581 QMessagePattern::~QMessagePattern()
582 {
583     for (int i = 0; literals[i] != 0; ++i)
584         delete [] literals[i];
585     delete [] literals;
586     literals = 0;
587     delete [] tokens;
588     tokens = 0;
589 }
590
591 Q_GLOBAL_STATIC(QMessagePattern, qMessagePattern)
592
593 /*!
594     \internal
595 */
596 Q_CORE_EXPORT QByteArray qMessageFormatString(QtMsgType type, const QMessageLogContext &context,
597                                               const char *str)
598 {
599     QByteArray message;
600
601     QMessagePattern *pattern = qMessagePattern();
602     if (!pattern) {
603         // after destruction of static QMessagePattern instance
604         message.append(str);
605         message.append('\n');
606         return message;
607     }
608
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) {
613             message.append(str);
614         } else if (token == typeTokenC) {
615             switch (type) {
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;
620             }
621         } else if (token == fileTokenC) {
622             if (context.file)
623                 message.append(context.file);
624             else
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));
631             else
632                 message.append("unknown");
633         } else {
634             message.append(token);
635         }
636     }
637     message.append('\n');
638     return message;
639 }
640
641 static QtMsgHandler msgHandler = 0;                // pointer to debug handler (without context)
642 static QMessageHandler messageHandler = 0;         // pointer to debug handler (with context)
643
644 /*!
645     \internal
646 */
647 static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &context,
648                                    const char *buf)
649 {
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()));
654 #else
655     fprintf(stderr, "%s", logMessage.constData());
656     fflush(stderr);
657 #endif
658 }
659
660 /*!
661     \internal
662 */
663 static void qDefaultMsgHandler(QtMsgType type, const char *buf)
664 {
665     QMessageLogContext emptyContext;
666     qDefaultMessageHandler(type, emptyContext, buf);
667 }
668
669 /*!
670     \internal
671 */
672 void qt_message_output(QtMsgType msgType, const QMessageLogContext &context, const char *buf)
673 {
674     if (!msgHandler)
675         msgHandler = qDefaultMsgHandler;
676     if (!messageHandler)
677         messageHandler = qDefaultMessageHandler;
678
679     // prefer new message handler over the old one
680     if (msgHandler == qDefaultMsgHandler
681             || messageHandler != qDefaultMessageHandler) {
682         (*messageHandler)(msgType, context, buf);
683     } else {
684         (*msgHandler)(msgType, buf);
685     }
686
687     if (msgType == QtFatalMsg
688             || (msgType == QtWarningMsg
689                 && (!qgetenv("QT_FATAL_WARNINGS").isNull())) ) {
690
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);
697 #else
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()));
702 #endif
703         if (ret == 0  && reportMode & _CRTDBG_MODE_WNDW)
704             return; // ignore
705         else if (ret == 1)
706             _CrtDbgBreak();
707 #endif
708
709 #if (defined(Q_OS_UNIX) || defined(Q_CC_MINGW))
710         abort(); // trap; generates core dump
711 #else
712         exit(1); // goodbye cruel world
713 #endif
714     }
715 }
716
717 void qErrnoWarning(const char *msg, ...)
718 {
719     // qt_error_string() will allocate anyway, so we don't have
720     // to be careful here (like we do in plain qWarning())
721     QString buf;
722     va_list ap;
723     va_start(ap, msg);
724     if (msg)
725         buf.vsprintf(msg, ap);
726     va_end(ap);
727
728     QMessageLogger().critical("%s (%s)", buf.toLocal8Bit().constData(),
729                               qt_error_string(-1).toLocal8Bit().constData());
730 }
731
732 void qErrnoWarning(int code, const char *msg, ...)
733 {
734     // qt_error_string() will allocate anyway, so we don't have
735     // to be careful here (like we do in plain qWarning())
736     QString buf;
737     va_list ap;
738     va_start(ap, msg);
739     if (msg)
740         buf.vsprintf(msg, ap);
741     va_end(ap);
742
743     QMessageLogger().critical("%s (%s)", buf.toLocal8Bit().constData(),
744                               qt_error_string(code).toLocal8Bit().constData());
745 }
746
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,
751                                              const char *str);
752 #endif
753
754 /*!
755     \typedef QtMsgHandler
756     \relates <QtGlobal>
757     \deprecated
758
759     This is a typedef for a pointer to a function with the following
760     signature:
761
762     \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 7
763
764     This typedef is deprecated, you should use QMessageHandler instead.
765     \sa QtMsgType, QMessageHandler, qInstallMsgHandler(), qInstallMessageHandler()
766 */
767
768 /*!
769     \typedef QMessageHandler
770     \relates <QtGlobal>
771     \since 5.0
772
773     This is a typedef for a pointer to a function with the following
774     signature:
775
776     \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 49
777
778     \sa QtMsgType, qInstallMessageHandler()
779 */
780
781 /*!
782     \fn QMessageHandler qInstallMessageHandler(QMessageHandler handler)
783     \relates <QtGlobal>
784     \since 5.0
785
786     Installs a Qt message \a handler which has been defined
787     previously. Returns a pointer to the previous message handler
788     (which may be 0).
789
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.
798
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.
802
803     Only one message handler can be defined, since this is usually
804     done on an application-wide basis to control debug output.
805
806     To restore the message handler, call \c qInstallMessageHandler(0).
807
808     Example:
809
810     \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 23
811
812     \sa qDebug(), qWarning(), qCritical(), qFatal(), QtMsgType,
813     {Debugging Techniques}
814 */
815
816 QMessageHandler qInstallMessageHandler(QMessageHandler h)
817 {
818     if (!messageHandler)
819         messageHandler = qDefaultMessageHandler;
820     QMessageHandler old = messageHandler;
821     messageHandler = h;
822 #if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB)
823     if (!messageHandler && usingWinMain)
824         messageHandler = qWinMessageHandler;
825 #endif
826     return old;
827 }
828
829 /*!
830     \fn QtMsgHandler qInstallMsgHandler(QtMsgHandler handler)
831     \relates <QtGlobal>
832     \deprecated
833
834     Installs a Qt message \a handler which has been defined
835     previously. This method is deprecated, use qInstallMessageHandler
836     instead.
837     \sa QtMsgHandler, qInstallMessageHandler
838 */
839
840 QtMsgHandler qInstallMsgHandler(QtMsgHandler h)
841 {
842     //if handler is 0, set it to the
843     //default message handler
844     if (!msgHandler)
845         msgHandler = qDefaultMsgHandler;
846     QtMsgHandler old = msgHandler;
847     msgHandler = h;
848 #if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB)
849     if (!msgHandler && usingWinMain)
850         msgHandler = qWinMsgHandler;
851 #endif
852     return old;
853 }
854
855 QT_END_NAMESPACE