1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Helper Library
3 * -------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Debug output utilities.
22 *//*--------------------------------------------------------------------*/
23
24 #include "qpDebugOut.h"
25
26 #include "qpCrashHandler.h" /*!< for QP_USE_SIGNAL_HANDLER */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30
31 typedef enum MessageType_e
32 {
33 MESSAGETYPE_INFO = 0,
34 MESSAGETYPE_ERROR,
35 MESSAGETYPE_NONFATAL_ERROR,
36
37 MESSAGETYPE_LAST
38 } MessageType;
39
40 static writePtr writeRedirect = 0;
41 static writeFtmPtr writeFtmRedirect = 0;
42
43 static void printRaw (MessageType type, const char* msg);
44 static void printFmt (MessageType type, const char* fmt, va_list args);
45 static void exitProcess (void);
46
qpRedirectOut(writePtr w,writeFtmPtr wftm)47 void qpRedirectOut (writePtr w, writeFtmPtr wftm)
48 {
49 writeRedirect = w;
50 writeFtmRedirect = wftm;
51 }
52
qpPrint(const char * message)53 void qpPrint (const char* message)
54 {
55 printRaw(MESSAGETYPE_INFO, message);
56 }
57
qpPrintf(const char * format,...)58 void qpPrintf (const char* format, ...)
59 {
60 va_list args;
61 va_start(args, format);
62 printFmt(MESSAGETYPE_INFO, format, args);
63 va_end(args);
64 }
65
qpPrintErrorf(const char * format,...)66 void qpPrintErrorf (const char* format, ...)
67 {
68 va_list args;
69 va_start(args, format);
70 printFmt(MESSAGETYPE_NONFATAL_ERROR, format, args);
71 va_end(args);
72 }
73
qpPrintv(const char * format,va_list args)74 void qpPrintv (const char* format, va_list args)
75 {
76 printFmt(MESSAGETYPE_INFO, format, args);
77 }
78
qpPrintErrorv(const char * format,va_list args)79 void qpPrintErrorv (const char* format, va_list args)
80 {
81 printFmt(MESSAGETYPE_NONFATAL_ERROR, format, args);
82 }
83
qpDief(const char * format,...)84 void qpDief (const char* format, ...)
85 {
86 va_list args;
87 va_start(args, format);
88 printFmt(MESSAGETYPE_ERROR, format, args);
89 va_end(args);
90
91 exitProcess();
92 }
93
qpDiev(const char * format,va_list args)94 void qpDiev (const char* format, va_list args)
95 {
96 printFmt(MESSAGETYPE_ERROR, format, args);
97 exitProcess();
98 }
99
100 /* print() implementation. */
101 #if (DE_OS == DE_OS_ANDROID)
102
103 #include <android/log.h>
104
getLogPriority(MessageType type)105 static android_LogPriority getLogPriority (MessageType type)
106 {
107 switch (type)
108 {
109 case MESSAGETYPE_INFO: return ANDROID_LOG_INFO;
110 case MESSAGETYPE_ERROR: return ANDROID_LOG_FATAL;
111 default: return ANDROID_LOG_DEBUG;
112 }
113 }
114
printRaw(MessageType type,const char * message)115 void printRaw (MessageType type, const char* message)
116 {
117 if (writeRedirect && !writeRedirect(type, message))
118 return;
119
120 __android_log_write(getLogPriority(type), "dEQP", message);
121 }
122
printFmt(MessageType type,const char * format,va_list args)123 void printFmt (MessageType type, const char* format, va_list args)
124 {
125 if (writeFtmRedirect && !writeFtmRedirect(type, format, args))
126 return;
127
128 __android_log_vprint(getLogPriority(type), "dEQP", format, args);
129 }
130
131 #else
132
getOutFile(MessageType type)133 static FILE* getOutFile (MessageType type)
134 {
135 if (type == MESSAGETYPE_ERROR || type == MESSAGETYPE_NONFATAL_ERROR)
136 return stderr;
137 else
138 return stdout;
139 }
140
printRaw(MessageType type,const char * message)141 void printRaw (MessageType type, const char* message)
142 {
143 if (writeRedirect && !writeRedirect(type, message))
144 return;
145
146 FILE* out = getOutFile(type);
147
148 if (type == MESSAGETYPE_ERROR)
149 fprintf(out, "FATAL ERROR: ");
150
151 fputs(message, out);
152
153 if (type == MESSAGETYPE_ERROR)
154 {
155 putc('\n', out);
156 fflush(out);
157 }
158 }
159
printFmt(MessageType type,const char * format,va_list args)160 void printFmt (MessageType type, const char* format, va_list args)
161 {
162 if (writeFtmRedirect && !writeFtmRedirect(type, format, args))
163 return;
164
165 FILE* out = getOutFile(type);
166
167 if (type == MESSAGETYPE_ERROR)
168 fprintf(out, "FATAL ERROR: ");
169
170 vfprintf(out, format, args);
171
172 if (type == MESSAGETYPE_ERROR)
173 {
174 putc('\n', out);
175 fflush(out);
176 }
177 }
178
179 #endif
180
181 /* exitProcess() implementation. */
182 #if (DE_OS == DE_OS_WIN32)
183
184 #define NOMINMAX
185 #define VC_EXTRALEAN
186 #define WIN32_LEAN_AND_MEAN
187 #include <windows.h>
188
exitProcess(void)189 static void exitProcess (void)
190 {
191 /* Some API implementations register atexit() functions that may hang.
192 By using TerminateProcess() we can avoid calling any potentially hanging exit routines. */
193 HANDLE curProc = GetCurrentProcess();
194 TerminateProcess(curProc, -1);
195 }
196
197 #else
198
199 #if (DE_OS == DE_OS_IOS)
200 # include "deThread.h" /*!< for deSleep() */
201 #endif
202
203 #if defined(QP_USE_SIGNAL_HANDLER)
204 # include <signal.h>
205 #endif
206
exitProcess(void)207 static void exitProcess (void)
208 {
209 #if (DE_OS == DE_OS_IOS)
210 /* Since tests are in the same process as execserver, we want to give it
211 a chance to stream complete log data before terminating. */
212 deSleep(5000);
213 #endif
214
215 #if defined(QP_USE_SIGNAL_HANDLER)
216 /* QP_USE_SIGNAL_HANDLER defined, this means this function could have
217 been called from a signal handler. Calling exit() inside a signal
218 handler is not safe. */
219
220 /* Flush all open FILES */
221 fflush(DE_NULL);
222
223 /* Kill without calling any _at_exit handlers as those might hang */
224 raise(SIGKILL);
225 #else
226 exit(-1);
227 #endif
228 }
229
230 #endif
231