• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2 * Copyright (C) 2014-2015 Intel Corporation.   All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 ****************************************************************************/
23 
24 #include "common/os.h"
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <assert.h>
28 #include <algorithm>
29 #include <mutex>
30 
31 #if SWR_ENABLE_ASSERTS || SWR_ENABLE_REL_ASSERTS
32 
33 #if defined(_WIN32)
34 #pragma comment(lib, "user32.lib")
35 #endif // _WIN32
36 
37 enum TextColor
38 {
39     TEXT_BLACK      = 0,
40     TEXT_RED        = 1,
41     TEXT_GREEN      = 2,
42     TEXT_BLUE       = 4,
43     TEXT_PURPLE     = TEXT_RED | TEXT_BLUE,
44     TEXT_CYAN       = TEXT_GREEN | TEXT_BLUE,
45     TEXT_YELLOW     = TEXT_RED | TEXT_GREEN,
46     TEXT_WHITE      = TEXT_RED | TEXT_GREEN | TEXT_BLUE,
47 };
48 
49 enum TextStyle
50 {
51     TEXT_NORMAL     = 0,
52     TEXT_INTENSITY  = 1,
53 };
54 
SetTextColor(FILE * stream,TextColor color=TEXT_WHITE,TextStyle style=TEXT_NORMAL)55 void SetTextColor(FILE* stream, TextColor color = TEXT_WHITE, TextStyle style = TEXT_NORMAL)
56 {
57 #if defined(_WIN32)
58 
59     HANDLE hConsoleHandle = nullptr;
60     if (stream == stderr)
61     {
62         hConsoleHandle = GetStdHandle(STD_ERROR_HANDLE);
63     }
64     else if (stream == stdout)
65     {
66         hConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
67     }
68     else
69     {
70         // Not a console stream, do nothing
71         return;
72     }
73 
74     WORD textAttributes = 0;
75     if (color & TEXT_RED)
76     {
77         textAttributes |= FOREGROUND_RED;
78     }
79     if (color & TEXT_GREEN)
80     {
81         textAttributes |= FOREGROUND_GREEN;
82     }
83     if (color & TEXT_BLUE)
84     {
85         textAttributes |= FOREGROUND_BLUE;
86     }
87     if (style & TEXT_INTENSITY)
88     {
89         textAttributes |= FOREGROUND_INTENSITY;
90     }
91     SetConsoleTextAttribute(hConsoleHandle, textAttributes);
92 
93 #else // !_WIN32
94 
95     // Print ANSI codes
96     uint32_t cc = 30 + (style ? 60 : 0) + color;
97     fprintf(stream, "\033[0m\033[%d;%dm", style, cc);
98 
99 #endif
100 }
101 
ResetTextColor(FILE * stream)102 void ResetTextColor(FILE* stream)
103 {
104 #if defined(_WIN32)
105 
106     SetTextColor(stream);
107 
108 #else // !_WIN32
109 
110     // Print ANSI codes
111     fprintf(stream, "\033[0m");
112 
113 #endif
114 }
115 
116 static std::mutex g_stderrMutex;
117 
SwrTrace(const char * pFileName,uint32_t lineNum,const char * function,const char * pFmtString,...)118 void SwrTrace(
119     const char* pFileName,
120     uint32_t    lineNum,
121     const char* function,
122     const char* pFmtString,
123     ...)
124 {
125     std::lock_guard<std::mutex> l(g_stderrMutex);
126 
127     SetTextColor(stderr, TEXT_CYAN, TEXT_NORMAL);
128 
129     fprintf(stderr, "%s(%d): TRACE in %s:\n", pFileName, lineNum, function);
130 
131     if (pFmtString)
132     {
133         SetTextColor(stderr, TEXT_PURPLE, TEXT_INTENSITY);
134         fprintf(stderr, "\t");
135         va_list args;
136         va_start(args, pFmtString);
137         vfprintf(stderr, pFmtString, args);
138         va_end(args);
139         fprintf(stderr, "\n");
140     }
141     ResetTextColor(stderr);
142     fflush(stderr);
143 
144 #if defined(_WIN32)
145     static const int MAX_MESSAGE_LEN = 2048;
146     char msgBuf[MAX_MESSAGE_LEN];
147 
148     sprintf_s(msgBuf, "%s(%d): TRACE in %s\n", pFileName, lineNum, function);
149     msgBuf[MAX_MESSAGE_LEN - 2] = '\n';
150     msgBuf[MAX_MESSAGE_LEN - 1] = 0;
151     OutputDebugStringA(msgBuf);
152 
153     int offset = 0;
154 
155     if (pFmtString)
156     {
157         va_list args;
158         va_start(args, pFmtString);
159         offset = _vsnprintf_s(
160             msgBuf,
161             sizeof(msgBuf),
162             sizeof(msgBuf),
163             pFmtString,
164             args);
165         va_end(args);
166 
167         if (offset < 0) { return; }
168 
169         OutputDebugStringA("\t");
170         OutputDebugStringA(msgBuf);
171         OutputDebugStringA("\n");
172     }
173 #endif // _WIN32
174 }
175 
SwrAssert(bool chkDebugger,bool & enabled,const char * pExpression,const char * pFileName,uint32_t lineNum,const char * pFunction,const char * pFmtString,...)176 bool SwrAssert(
177     bool        chkDebugger,
178     bool&       enabled,
179     const char* pExpression,
180     const char* pFileName,
181     uint32_t    lineNum,
182     const char* pFunction,
183     const char* pFmtString /* = nullptr */,
184     ...)
185 {
186     {
187         std::lock_guard<std::mutex> l(g_stderrMutex);
188 
189         SetTextColor(stderr, TEXT_CYAN, TEXT_NORMAL);
190 
191         fprintf(stderr, "%s(%d): ", pFileName, lineNum);
192 
193         SetTextColor(stderr, TEXT_RED, TEXT_INTENSITY);
194 
195         fprintf(stderr, "ASSERT: %s\n", pExpression);
196 
197         SetTextColor(stderr, TEXT_CYAN, TEXT_INTENSITY);
198         fprintf(stderr, "\t%s\n", pFunction);
199 
200         if (pFmtString)
201         {
202             SetTextColor(stderr, TEXT_YELLOW, TEXT_INTENSITY);
203             fprintf(stderr, "\t");
204             va_list args;
205             va_start(args, pFmtString);
206             vfprintf(stderr, pFmtString, args);
207             va_end(args);
208             fprintf(stderr, "\n");
209         }
210         ResetTextColor(stderr);
211         fflush(stderr);
212     }
213 
214 #if defined(_WIN32)
215     static const int MAX_MESSAGE_LEN = 2048;
216     char msgBuf[MAX_MESSAGE_LEN];
217 
218     sprintf_s(msgBuf, "%s(%d): ASSERT: %s\n", pFileName, lineNum, pExpression);
219     msgBuf[MAX_MESSAGE_LEN - 2] = '\n';
220     msgBuf[MAX_MESSAGE_LEN - 1] = 0;
221     OutputDebugStringA(msgBuf);
222 
223     sprintf_s(msgBuf, "\t%s\n", pFunction);
224     msgBuf[MAX_MESSAGE_LEN - 2] = '\n';
225     msgBuf[MAX_MESSAGE_LEN - 1] = 0;
226     OutputDebugStringA(msgBuf);
227 
228     int offset = 0;
229 
230     if (pFmtString)
231     {
232         va_list args;
233         va_start(args, pFmtString);
234         offset = _vsnprintf_s(
235             msgBuf,
236             sizeof(msgBuf),
237             sizeof(msgBuf),
238             pFmtString,
239             args);
240         va_end(args);
241 
242         if (offset < 0) { return true; }
243 
244         OutputDebugStringA("\t");
245         OutputDebugStringA(msgBuf);
246         OutputDebugStringA("\n");
247     }
248 
249     if (enabled && KNOB_ENABLE_ASSERT_DIALOGS)
250     {
251         int retval = sprintf_s(
252             &msgBuf[offset],
253             MAX_MESSAGE_LEN - offset,
254             "\n\n"
255             "File: %s\n"
256             "Line: %d\n"
257             "\n"
258             "Expression: %s\n\n"
259             "Cancel: Disable this assert for the remainder of the process\n"
260             "Try Again: Break into the debugger\n"
261             "Continue: Continue execution (but leave assert enabled)",
262             pFileName,
263             lineNum,
264             pExpression);
265 
266         if (retval < 0) { return true; }
267 
268         offset += retval;
269 
270         if (!IsDebuggerPresent())
271         {
272             sprintf_s(
273                 &msgBuf[offset],
274                 MAX_MESSAGE_LEN - offset,
275                 "\n\n*** NO DEBUGGER DETECTED ***\n\nPressing \"Try Again\" will cause a program crash!");
276         }
277 
278         retval = MessageBoxA(nullptr, msgBuf, "Assert Failed", MB_CANCELTRYCONTINUE | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
279 
280         switch (retval)
281         {
282         case IDCANCEL:
283             enabled = false;
284             return false;
285 
286         case IDTRYAGAIN:
287             return true;
288 
289         case IDCONTINUE:
290             return false;
291         }
292     }
293     else
294     {
295         return (IsDebuggerPresent() || !chkDebugger) && enabled;
296     }
297 #endif // _WIN32
298 
299     return enabled;
300 }
301 
302 #endif // SWR_ENABLE_ASSERTS
303