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 void printRaw (MessageType type, const char* msg);
41 static void printFmt (MessageType type, const char* fmt, va_list args);
42 static void exitProcess (void);
43
qpPrint(const char * message)44 void qpPrint (const char* message)
45 {
46 printRaw(MESSAGETYPE_INFO, message);
47 }
48
qpPrintf(const char * format,...)49 void qpPrintf (const char* format, ...)
50 {
51 va_list args;
52 va_start(args, format);
53 printFmt(MESSAGETYPE_INFO, format, args);
54 va_end(args);
55 }
56
qpPrintErrorf(const char * format,...)57 void qpPrintErrorf (const char* format, ...)
58 {
59 va_list args;
60 va_start(args, format);
61 printFmt(MESSAGETYPE_NONFATAL_ERROR, format, args);
62 va_end(args);
63 }
64
qpPrintv(const char * format,va_list args)65 void qpPrintv (const char* format, va_list args)
66 {
67 printFmt(MESSAGETYPE_INFO, format, args);
68 }
69
qpPrintErrorv(const char * format,va_list args)70 void qpPrintErrorv (const char* format, va_list args)
71 {
72 printFmt(MESSAGETYPE_NONFATAL_ERROR, format, args);
73 }
74
qpDief(const char * format,...)75 void qpDief (const char* format, ...)
76 {
77 va_list args;
78 va_start(args, format);
79 printFmt(MESSAGETYPE_ERROR, format, args);
80 va_end(args);
81
82 exitProcess();
83 }
84
qpDiev(const char * format,va_list args)85 void qpDiev (const char* format, va_list args)
86 {
87 printFmt(MESSAGETYPE_ERROR, format, args);
88 exitProcess();
89 }
90
91 /* print() implementation. */
92 #if (DE_OS == DE_OS_ANDROID)
93
94 #include <android/log.h>
95
getLogPriority(MessageType type)96 static android_LogPriority getLogPriority (MessageType type)
97 {
98 switch (type)
99 {
100 case MESSAGETYPE_INFO: return ANDROID_LOG_INFO;
101 case MESSAGETYPE_ERROR: return ANDROID_LOG_FATAL;
102 default: return ANDROID_LOG_DEBUG;
103 }
104 }
105
printRaw(MessageType type,const char * message)106 void printRaw (MessageType type, const char* message)
107 {
108 __android_log_write(getLogPriority(type), "dEQP", message);
109 }
110
printFmt(MessageType type,const char * format,va_list args)111 void printFmt (MessageType type, const char* format, va_list args)
112 {
113 __android_log_vprint(getLogPriority(type), "dEQP", format, args);
114 }
115
116 #else
117
getOutFile(MessageType type)118 static FILE* getOutFile (MessageType type)
119 {
120 if (type == MESSAGETYPE_ERROR || type == MESSAGETYPE_NONFATAL_ERROR)
121 return stderr;
122 else
123 return stdout;
124 }
125
printRaw(MessageType type,const char * message)126 void printRaw (MessageType type, const char* message)
127 {
128 FILE* out = getOutFile(type);
129
130 if (type == MESSAGETYPE_ERROR)
131 fprintf(out, "FATAL ERROR: ");
132
133 fputs(message, out);
134
135 if (type == MESSAGETYPE_ERROR)
136 {
137 putc('\n', out);
138 fflush(out);
139 }
140 }
141
printFmt(MessageType type,const char * format,va_list args)142 void printFmt (MessageType type, const char* format, va_list args)
143 {
144 FILE* out = getOutFile(type);
145
146 if (type == MESSAGETYPE_ERROR)
147 fprintf(out, "FATAL ERROR: ");
148
149 vfprintf(out, format, args);
150
151 if (type == MESSAGETYPE_ERROR)
152 {
153 putc('\n', out);
154 fflush(out);
155 }
156 }
157
158 #endif
159
160 /* exitProcess() implementation. */
161 #if (DE_OS == DE_OS_WIN32)
162
163 #define NOMINMAX
164 #define VC_EXTRALEAN
165 #define WIN32_LEAN_AND_MEAN
166 #include <windows.h>
167
exitProcess(void)168 static void exitProcess (void)
169 {
170 /* Some API implementations register atexit() functions that may hang.
171 By using TerminateProcess() we can avoid calling any potentially hanging exit routines. */
172 HANDLE curProc = GetCurrentProcess();
173 TerminateProcess(curProc, -1);
174 }
175
176 #else
177
178 #if (DE_OS == DE_OS_IOS)
179 # include "deThread.h" /*!< for deSleep() */
180 #endif
181
182 #if defined(QP_USE_SIGNAL_HANDLER)
183 # include <signal.h>
184 #endif
185
exitProcess(void)186 static void exitProcess (void)
187 {
188 #if (DE_OS == DE_OS_IOS)
189 /* Since tests are in the same process as execserver, we want to give it
190 a chance to stream complete log data before terminating. */
191 deSleep(5000);
192 #endif
193
194 #if defined(QP_USE_SIGNAL_HANDLER)
195 /* QP_USE_SIGNAL_HANDLER defined, this means this function could have
196 been called from a signal handler. Calling exit() inside a signal
197 handler is not safe. */
198
199 /* Flush all open FILES */
200 fflush(DE_NULL);
201
202 /* Kill without calling any _at_exit handlers as those might hang */
203 raise(SIGKILL);
204 #else
205 exit(-1);
206 #endif
207 }
208
209 #endif
210