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