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:
110 return ANDROID_LOG_INFO;
111 case MESSAGETYPE_ERROR:
112 return ANDROID_LOG_FATAL;
113 default:
114 return ANDROID_LOG_DEBUG;
115 }
116 }
117
printRaw(MessageType type,const char * message)118 void printRaw(MessageType type, const char *message)
119 {
120 if (writeRedirect && !writeRedirect(type, message))
121 return;
122
123 __android_log_write(getLogPriority(type), "dEQP", message);
124 }
125
printFmt(MessageType type,const char * format,va_list args)126 void printFmt(MessageType type, const char *format, va_list args)
127 {
128 if (writeFtmRedirect && !writeFtmRedirect(type, format, args))
129 return;
130
131 __android_log_vprint(getLogPriority(type), "dEQP", format, args);
132 }
133
134 #else
135
getOutFile(MessageType type)136 static FILE *getOutFile(MessageType type)
137 {
138 if (type == MESSAGETYPE_ERROR || type == MESSAGETYPE_NONFATAL_ERROR)
139 return stderr;
140 else
141 return stdout;
142 }
143
printRaw(MessageType type,const char * message)144 void printRaw(MessageType type, const char *message)
145 {
146 if (writeRedirect && !writeRedirect(type, message))
147 return;
148
149 FILE *out = getOutFile(type);
150
151 if (type == MESSAGETYPE_ERROR)
152 fprintf(out, "FATAL ERROR: ");
153
154 fputs(message, out);
155
156 if (type == MESSAGETYPE_ERROR)
157 {
158 putc('\n', out);
159 fflush(out);
160 }
161 }
162
printFmt(MessageType type,const char * format,va_list args)163 void printFmt(MessageType type, const char *format, va_list args)
164 {
165 if (writeFtmRedirect && !writeFtmRedirect(type, format, args))
166 return;
167
168 FILE *out = getOutFile(type);
169
170 if (type == MESSAGETYPE_ERROR)
171 fprintf(out, "FATAL ERROR: ");
172
173 vfprintf(out, format, args);
174
175 if (type == MESSAGETYPE_ERROR)
176 {
177 putc('\n', out);
178 fflush(out);
179 }
180 }
181
182 #endif
183
184 /* exitProcess() implementation. */
185 #if (DE_OS == DE_OS_WIN32)
186
187 #define NOMINMAX
188 #define VC_EXTRALEAN
189 #define WIN32_LEAN_AND_MEAN
190 #include <windows.h>
191
exitProcess(void)192 static void exitProcess(void)
193 {
194 /* Some API implementations register atexit() functions that may hang.
195 By using TerminateProcess() we can avoid calling any potentially hanging exit routines. */
196 HANDLE curProc = GetCurrentProcess();
197 TerminateProcess(curProc, -1);
198 }
199
200 #else
201
202 #if (DE_OS == DE_OS_IOS)
203 #include "deThread.h" /*!< for deSleep() */
204 #endif
205
206 #if defined(QP_USE_SIGNAL_HANDLER)
207 #include <signal.h>
208 #endif
209
exitProcess(void)210 static void exitProcess(void)
211 {
212 #if (DE_OS == DE_OS_IOS)
213 /* Since tests are in the same process as execserver, we want to give it
214 a chance to stream complete log data before terminating. */
215 deSleep(5000);
216 #endif
217
218 #if defined(QP_USE_SIGNAL_HANDLER)
219 /* QP_USE_SIGNAL_HANDLER defined, this means this function could have
220 been called from a signal handler. Calling exit() inside a signal
221 handler is not safe. */
222
223 /* Flush all open FILES */
224 fflush(DE_NULL);
225
226 /* Kill without calling any _at_exit handlers as those might hang */
227 raise(SIGKILL);
228 #else
229 exit(-1);
230 #endif
231 }
232
233 #endif
234